@fluidframework/tree 2.103.0 → 2.110.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/api-report/tree.alpha.api.md +12 -3
  3. package/api-report/tree.beta.api.md +11 -3
  4. package/api-report/tree.legacy.beta.api.md +11 -3
  5. package/dist/codec/versioned/format.js +2 -24
  6. package/dist/codec/versioned/format.js.map +1 -1
  7. package/dist/core/rebase/types.js +2 -24
  8. package/dist/core/rebase/types.js.map +1 -1
  9. package/dist/core/schema-stored/formatV1.js +2 -24
  10. package/dist/core/schema-stored/formatV1.js.map +1 -1
  11. package/dist/core/schema-stored/formatV2.js +2 -24
  12. package/dist/core/schema-stored/formatV2.js.map +1 -1
  13. package/dist/core/schema-stored/index.js +3 -25
  14. package/dist/core/schema-stored/index.js.map +1 -1
  15. package/dist/core/tree/anchorSet.js +4 -8
  16. package/dist/core/tree/anchorSet.js.map +1 -1
  17. package/dist/core/tree/detachedFieldIndexFormatCommon.js +2 -24
  18. package/dist/core/tree/detachedFieldIndexFormatCommon.js.map +1 -1
  19. package/dist/core/tree/detachedFieldIndexFormatV2.js +2 -24
  20. package/dist/core/tree/detachedFieldIndexFormatV2.js.map +1 -1
  21. package/dist/core/tree/persistedTreeTextFormat.js +2 -24
  22. package/dist/core/tree/persistedTreeTextFormat.js.map +1 -1
  23. package/dist/entrypoints/internal.js +2 -15
  24. package/dist/entrypoints/internal.js.map +1 -1
  25. package/dist/feature-libraries/chunked-forest/chunkedForest.js +7 -11
  26. package/dist/feature-libraries/chunked-forest/chunkedForest.js.map +1 -1
  27. package/dist/feature-libraries/chunked-forest/codec/format/formatGeneric.js +2 -24
  28. package/dist/feature-libraries/chunked-forest/codec/format/formatGeneric.js.map +1 -1
  29. package/dist/feature-libraries/chunked-forest/codec/format/formatV1.js +2 -24
  30. package/dist/feature-libraries/chunked-forest/codec/format/formatV1.js.map +1 -1
  31. package/dist/feature-libraries/chunked-forest/codec/format/formatV2.js +2 -24
  32. package/dist/feature-libraries/chunked-forest/codec/format/formatV2.js.map +1 -1
  33. package/dist/feature-libraries/chunked-forest/codec/format/formatVText.js +2 -24
  34. package/dist/feature-libraries/chunked-forest/codec/format/formatVText.js.map +1 -1
  35. package/dist/feature-libraries/flex-tree/lazyEntity.js +9 -19
  36. package/dist/feature-libraries/flex-tree/lazyEntity.js.map +1 -1
  37. package/dist/feature-libraries/flex-tree/lazyNode.js +3 -13
  38. package/dist/feature-libraries/flex-tree/lazyNode.js.map +1 -1
  39. package/dist/feature-libraries/forest-summary/formatCommon.js +2 -24
  40. package/dist/feature-libraries/forest-summary/formatCommon.js.map +1 -1
  41. package/dist/feature-libraries/index.js +2 -24
  42. package/dist/feature-libraries/index.js.map +1 -1
  43. package/dist/feature-libraries/modular-schema/genericFieldKindFormat.js +2 -24
  44. package/dist/feature-libraries/modular-schema/genericFieldKindFormat.js.map +1 -1
  45. package/dist/feature-libraries/modular-schema/modularChangeFamily.d.ts.map +1 -1
  46. package/dist/feature-libraries/modular-schema/modularChangeFamily.js +10 -30
  47. package/dist/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
  48. package/dist/feature-libraries/modular-schema/modularChangeFormatV1.js +2 -24
  49. package/dist/feature-libraries/modular-schema/modularChangeFormatV1.js.map +1 -1
  50. package/dist/feature-libraries/modular-schema/modularChangeFormatV2.js +2 -24
  51. package/dist/feature-libraries/modular-schema/modularChangeFormatV2.js.map +1 -1
  52. package/dist/feature-libraries/modular-schema/modularChangeTypes.d.ts +0 -5
  53. package/dist/feature-libraries/modular-schema/modularChangeTypes.d.ts.map +1 -1
  54. package/dist/feature-libraries/modular-schema/modularChangeTypes.js.map +1 -1
  55. package/dist/feature-libraries/object-forest/objectForest.js +11 -55
  56. package/dist/feature-libraries/object-forest/objectForest.js.map +1 -1
  57. package/dist/feature-libraries/optional-field/optionalFieldChangeFormatV1.js +2 -24
  58. package/dist/feature-libraries/optional-field/optionalFieldChangeFormatV1.js.map +1 -1
  59. package/dist/feature-libraries/optional-field/optionalFieldChangeFormatV2.js +2 -24
  60. package/dist/feature-libraries/optional-field/optionalFieldChangeFormatV2.js.map +1 -1
  61. package/dist/feature-libraries/schema-edits/schemaChangeFormat.js +2 -24
  62. package/dist/feature-libraries/schema-edits/schemaChangeFormat.js.map +1 -1
  63. package/dist/feature-libraries/schema-index/formatV1.js +2 -24
  64. package/dist/feature-libraries/schema-index/formatV1.js.map +1 -1
  65. package/dist/feature-libraries/schema-index/formatV2.js +2 -24
  66. package/dist/feature-libraries/schema-index/formatV2.js.map +1 -1
  67. package/dist/feature-libraries/sequence-field/formatV1.js +2 -24
  68. package/dist/feature-libraries/sequence-field/formatV1.js.map +1 -1
  69. package/dist/feature-libraries/sequence-field/formatV2.js +2 -24
  70. package/dist/feature-libraries/sequence-field/formatV2.js.map +1 -1
  71. package/dist/feature-libraries/sequence-field/formatV3.js +2 -24
  72. package/dist/feature-libraries/sequence-field/formatV3.js.map +1 -1
  73. package/dist/index.js +2 -24
  74. package/dist/index.js.map +1 -1
  75. package/dist/packageVersion.d.ts +1 -1
  76. package/dist/packageVersion.js +1 -1
  77. package/dist/packageVersion.js.map +1 -1
  78. package/dist/shared-tree/schematizingTreeView.d.ts +1 -0
  79. package/dist/shared-tree/schematizingTreeView.d.ts.map +1 -1
  80. package/dist/shared-tree/schematizingTreeView.js +7 -41
  81. package/dist/shared-tree/schematizingTreeView.js.map +1 -1
  82. package/dist/shared-tree/sharedTree.d.ts +0 -1
  83. package/dist/shared-tree/sharedTree.d.ts.map +1 -1
  84. package/dist/shared-tree/sharedTree.js +6 -45
  85. package/dist/shared-tree/sharedTree.js.map +1 -1
  86. package/dist/shared-tree/sharedTreeChangeFormat.js +2 -24
  87. package/dist/shared-tree/sharedTreeChangeFormat.js.map +1 -1
  88. package/dist/shared-tree/treeCheckout.d.ts +12 -3
  89. package/dist/shared-tree/treeCheckout.d.ts.map +1 -1
  90. package/dist/shared-tree/treeCheckout.js +106 -136
  91. package/dist/shared-tree/treeCheckout.js.map +1 -1
  92. package/dist/shared-tree-core/branch.js +13 -17
  93. package/dist/shared-tree-core/branch.js.map +1 -1
  94. package/dist/shared-tree-core/editManagerFormatCommons.js +2 -24
  95. package/dist/shared-tree-core/editManagerFormatCommons.js.map +1 -1
  96. package/dist/shared-tree-core/editManagerFormatV1toV4.js +2 -24
  97. package/dist/shared-tree-core/editManagerFormatV1toV4.js.map +1 -1
  98. package/dist/shared-tree-core/editManagerFormatVSharedBranches.js +2 -24
  99. package/dist/shared-tree-core/editManagerFormatVSharedBranches.js.map +1 -1
  100. package/dist/shared-tree-core/messageCodecVSharedBranches.js +2 -24
  101. package/dist/shared-tree-core/messageCodecVSharedBranches.js.map +1 -1
  102. package/dist/shared-tree-core/messageFormatV1ToV4.js +2 -24
  103. package/dist/shared-tree-core/messageFormatV1ToV4.js.map +1 -1
  104. package/dist/shared-tree-core/messageFormatVSharedBranches.js +2 -24
  105. package/dist/shared-tree-core/messageFormatVSharedBranches.js.map +1 -1
  106. package/dist/shared-tree-core/sharedTreeCore.js +6 -43
  107. package/dist/shared-tree-core/sharedTreeCore.js.map +1 -1
  108. package/dist/shared-tree-core/transaction.js +20 -30
  109. package/dist/shared-tree-core/transaction.js.map +1 -1
  110. package/dist/simple-tree/api/simpleSchemaCodec.js +2 -24
  111. package/dist/simple-tree/api/simpleSchemaCodec.js.map +1 -1
  112. package/dist/simple-tree/api/snapshotCompatibilityChecker.js +2 -24
  113. package/dist/simple-tree/api/snapshotCompatibilityChecker.js.map +1 -1
  114. package/dist/simple-tree/api/tree.d.ts +10 -0
  115. package/dist/simple-tree/api/tree.d.ts.map +1 -1
  116. package/dist/simple-tree/api/tree.js.map +1 -1
  117. package/dist/simple-tree/core/treeNodeKernel.js +83 -93
  118. package/dist/simple-tree/core/treeNodeKernel.js.map +1 -1
  119. package/dist/simple-tree/core/unhydratedFlexTree.js +6 -10
  120. package/dist/simple-tree/core/unhydratedFlexTree.js.map +1 -1
  121. package/dist/simple-tree/leafNodeSchema.js +2 -12
  122. package/dist/simple-tree/leafNodeSchema.js.map +1 -1
  123. package/dist/simple-tree/node-kinds/array/arrayNode.js +2 -6
  124. package/dist/simple-tree/node-kinds/array/arrayNode.js.map +1 -1
  125. package/dist/simple-tree/simpleSchemaFormatV1.js +2 -24
  126. package/dist/simple-tree/simpleSchemaFormatV1.js.map +1 -1
  127. package/dist/tableSchema.d.ts +50 -4
  128. package/dist/tableSchema.d.ts.map +1 -1
  129. package/dist/tableSchema.js +202 -106
  130. package/dist/tableSchema.js.map +1 -1
  131. package/dist/util/arrayUtilities.d.ts +20 -0
  132. package/dist/util/arrayUtilities.d.ts.map +1 -1
  133. package/dist/util/arrayUtilities.js +24 -1
  134. package/dist/util/arrayUtilities.js.map +1 -1
  135. package/dist/util/index.d.ts +1 -1
  136. package/dist/util/index.d.ts.map +1 -1
  137. package/dist/util/index.js +3 -2
  138. package/dist/util/index.js.map +1 -1
  139. package/dist/util/rangeMap.d.ts +13 -0
  140. package/dist/util/rangeMap.d.ts.map +1 -1
  141. package/dist/util/rangeMap.js +69 -8
  142. package/dist/util/rangeMap.js.map +1 -1
  143. package/dist/util/typeboxBrand.js +2 -24
  144. package/dist/util/typeboxBrand.js.map +1 -1
  145. package/dist/util/utils.js +2 -24
  146. package/dist/util/utils.js.map +1 -1
  147. package/eslint.config.mts +0 -30
  148. package/lib/core/tree/anchorSet.js +1 -5
  149. package/lib/core/tree/anchorSet.js.map +1 -1
  150. package/lib/feature-libraries/chunked-forest/chunkedForest.js +1 -5
  151. package/lib/feature-libraries/chunked-forest/chunkedForest.js.map +1 -1
  152. package/lib/feature-libraries/flex-tree/lazyEntity.js +1 -11
  153. package/lib/feature-libraries/flex-tree/lazyEntity.js.map +1 -1
  154. package/lib/feature-libraries/flex-tree/lazyNode.js +1 -11
  155. package/lib/feature-libraries/flex-tree/lazyNode.js.map +1 -1
  156. package/lib/feature-libraries/modular-schema/modularChangeFamily.d.ts.map +1 -1
  157. package/lib/feature-libraries/modular-schema/modularChangeFamily.js +10 -30
  158. package/lib/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
  159. package/lib/feature-libraries/modular-schema/modularChangeTypes.d.ts +0 -5
  160. package/lib/feature-libraries/modular-schema/modularChangeTypes.d.ts.map +1 -1
  161. package/lib/feature-libraries/modular-schema/modularChangeTypes.js.map +1 -1
  162. package/lib/feature-libraries/object-forest/objectForest.js +1 -45
  163. package/lib/feature-libraries/object-forest/objectForest.js.map +1 -1
  164. package/lib/packageVersion.d.ts +1 -1
  165. package/lib/packageVersion.js +1 -1
  166. package/lib/packageVersion.js.map +1 -1
  167. package/lib/shared-tree/schematizingTreeView.d.ts +1 -0
  168. package/lib/shared-tree/schematizingTreeView.d.ts.map +1 -1
  169. package/lib/shared-tree/schematizingTreeView.js +4 -38
  170. package/lib/shared-tree/schematizingTreeView.js.map +1 -1
  171. package/lib/shared-tree/sharedTree.d.ts +0 -1
  172. package/lib/shared-tree/sharedTree.d.ts.map +1 -1
  173. package/lib/shared-tree/sharedTree.js +1 -40
  174. package/lib/shared-tree/sharedTree.js.map +1 -1
  175. package/lib/shared-tree/treeCheckout.d.ts +12 -3
  176. package/lib/shared-tree/treeCheckout.d.ts.map +1 -1
  177. package/lib/shared-tree/treeCheckout.js +62 -92
  178. package/lib/shared-tree/treeCheckout.js.map +1 -1
  179. package/lib/shared-tree-core/branch.js +1 -5
  180. package/lib/shared-tree-core/branch.js.map +1 -1
  181. package/lib/shared-tree-core/sharedTreeCore.js +1 -38
  182. package/lib/shared-tree-core/sharedTreeCore.js.map +1 -1
  183. package/lib/shared-tree-core/transaction.js +1 -11
  184. package/lib/shared-tree-core/transaction.js.map +1 -1
  185. package/lib/simple-tree/api/tree.d.ts +10 -0
  186. package/lib/simple-tree/api/tree.d.ts.map +1 -1
  187. package/lib/simple-tree/api/tree.js.map +1 -1
  188. package/lib/simple-tree/core/treeNodeKernel.js +1 -11
  189. package/lib/simple-tree/core/treeNodeKernel.js.map +1 -1
  190. package/lib/simple-tree/core/unhydratedFlexTree.js +1 -5
  191. package/lib/simple-tree/core/unhydratedFlexTree.js.map +1 -1
  192. package/lib/simple-tree/leafNodeSchema.js +1 -11
  193. package/lib/simple-tree/leafNodeSchema.js.map +1 -1
  194. package/lib/simple-tree/node-kinds/array/arrayNode.js +1 -5
  195. package/lib/simple-tree/node-kinds/array/arrayNode.js.map +1 -1
  196. package/lib/tableSchema.d.ts +50 -4
  197. package/lib/tableSchema.d.ts.map +1 -1
  198. package/lib/tableSchema.js +171 -75
  199. package/lib/tableSchema.js.map +1 -1
  200. package/lib/util/arrayUtilities.d.ts +20 -0
  201. package/lib/util/arrayUtilities.d.ts.map +1 -1
  202. package/lib/util/arrayUtilities.js +22 -0
  203. package/lib/util/arrayUtilities.js.map +1 -1
  204. package/lib/util/index.d.ts +1 -1
  205. package/lib/util/index.d.ts.map +1 -1
  206. package/lib/util/index.js +1 -1
  207. package/lib/util/index.js.map +1 -1
  208. package/lib/util/rangeMap.d.ts +13 -0
  209. package/lib/util/rangeMap.d.ts.map +1 -1
  210. package/lib/util/rangeMap.js +69 -8
  211. package/lib/util/rangeMap.js.map +1 -1
  212. package/package.json +24 -23
  213. package/src/feature-libraries/modular-schema/modularChangeFamily.ts +14 -47
  214. package/src/feature-libraries/modular-schema/modularChangeTypes.ts +0 -5
  215. package/src/packageVersion.ts +1 -1
  216. package/src/shared-tree/schematizingTreeView.ts +4 -0
  217. package/src/shared-tree/sharedTree.ts +2 -6
  218. package/src/shared-tree/treeCheckout.ts +59 -51
  219. package/src/simple-tree/api/tree.ts +11 -0
  220. package/src/tableSchema.ts +306 -80
  221. package/src/util/arrayUtilities.ts +35 -0
  222. package/src/util/index.ts +2 -0
  223. package/src/util/rangeMap.ts +108 -9
  224. package/tsconfig.json +5 -0
@@ -1 +1 @@
1
- {"version":3,"file":"arrayUtilities.d.ts","sourceRoot":"","sources":["../../src/util/arrayUtilities.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAIxE;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAK1E;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC5B,KAAK,EAAE,MAAM,EACb,KAAK,EAAE;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAClC,OAAO,EAAE,MAAM,EACf,eAAe,GAAE,OAAe,GAC9B,IAAI,CAeN;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CACjC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAClC,OAAO,EAAE,MAAM,GACb,IAAI,CAQN"}
1
+ {"version":3,"file":"arrayUtilities.d.ts","sourceRoot":"","sources":["../../src/util/arrayUtilities.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAIxE;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAK1E;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC5B,KAAK,EAAE,MAAM,EACb,KAAK,EAAE;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAClC,OAAO,EAAE,MAAM,EACf,eAAe,GAAE,OAAe,GAC9B,IAAI,CAeN;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CACjC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAClC,OAAO,EAAE,MAAM,GACb,IAAI,CAQN;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IAC1B,8BAA8B;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,4BAA4B;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,EACxC,KAAK,EAAE;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,CAAA;CAAE,EAC/D,aAAa,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,GACjC,SAAS,UAAU,EAAE,CAavB"}
@@ -66,4 +66,26 @@ export function validateIndexRange(startIndex, endIndex, array, apiName) {
66
66
  validateIndex(startIndex, array, apiName, true);
67
67
  validateIndex(endIndex, array, apiName, true);
68
68
  }
69
+ /**
70
+ * Walks `array` in order and collects the indices of every element for which `predicate` returns
71
+ * `true` into contiguous `[start, end)` ranges.
72
+ * @param array - The array (or array-like) to scan.
73
+ * @param shouldInclude - Returns `true` for elements whose indices should be included.
74
+ * @returns The collected ranges in ascending order. The returned array is empty if no elements match.
75
+ */
76
+ export function collectContiguousRanges(array, shouldInclude) {
77
+ const ranges = [];
78
+ for (let i = 0; i < array.length; i++) {
79
+ if (shouldInclude(array[i])) {
80
+ const last = ranges[ranges.length - 1];
81
+ if (last?.end === i) {
82
+ last.end = i + 1;
83
+ }
84
+ else {
85
+ ranges.push({ start: i, end: i + 1 });
86
+ }
87
+ }
88
+ }
89
+ return ranges;
90
+ }
69
91
  //# sourceMappingURL=arrayUtilities.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"arrayUtilities.js","sourceRoot":"","sources":["../../src/util/arrayUtilities.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAC;AAEtE;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAa,EAAE,OAAe;IACjE,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,UAAU,CAAC,qCAAqC,OAAO,SAAS,KAAK,GAAG,CAAC,CAAC;IACrF,CAAC;AACF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAa,EAAE,OAAe;IACnE,mBAAmB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACpC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACf,MAAM,IAAI,UAAU,CAAC,yCAAyC,OAAO,SAAS,KAAK,GAAG,CAAC,CAAC;IACzF,CAAC;AACF,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAC5B,KAAa,EACb,KAAkC,EAClC,OAAe,EACf,kBAA2B,KAAK;IAEhC,qBAAqB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACtC,IAAI,eAAe,EAAE,CAAC;QACrB,IAAI,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YAC1B,MAAM,IAAI,UAAU,CACnB,yBAAyB,OAAO,uCAAuC,KAAK,CAAC,MAAM,SAAS,KAAK,GAAG,CACpG,CAAC;QACH,CAAC;IACF,CAAC;SAAM,CAAC;QACP,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YAC3B,MAAM,IAAI,UAAU,CACnB,yBAAyB,OAAO,uCAAuC,KAAK,CAAC,MAAM,GAAG,CAAC,SAAS,KAAK,GAAG,CACxG,CAAC;QACH,CAAC;IACF,CAAC;AACF,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,kBAAkB,CACjC,UAAkB,EAClB,QAAgB,EAChB,KAAkC,EAClC,OAAe;IAEf,IAAI,UAAU,GAAG,QAAQ,EAAE,CAAC;QAC3B,MAAM,IAAI,UAAU,CACnB,6BAA6B,OAAO,iBAAiB,UAAU,8BAA8B,QAAQ,GAAG,CACxG,CAAC;IACH,CAAC;IACD,aAAa,CAAC,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAChD,aAAa,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;AAC/C,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { UsageError } from \"@fluidframework/telemetry-utils/internal\";\n\n/**\n * Validates that the provided index is a safe integer.\n * @throws If the index is invalid.\n * @param index - The index to validate.\n * @param apiName - The name of the API performing the validation.\n * @throws If the index is invalid.\n */\nexport function validateSafeInteger(index: number, apiName: string): void {\n\tif (!Number.isSafeInteger(index)) {\n\t\tthrow new UsageError(`Expected a safe integer passed to ${apiName}, got ${index}.`);\n\t}\n}\n\n/**\n * Validates that the provided index is a 0 or greater safe integer.\n * @param index - The index to validate.\n * @param apiName - The name of the API performing the validation.\n * @throws If the index is invalid.\n */\nexport function validatePositiveIndex(index: number, apiName: string): void {\n\tvalidateSafeInteger(index, apiName);\n\tif (index < 0) {\n\t\tthrow new UsageError(`Expected non-negative index passed to ${apiName}, got ${index}.`);\n\t}\n}\n\n/**\n * Validates that the provided index is a non-negative safe integer within the bounds of the provided array (or, optionally, 1 past its end).\n * @throws If the index is invalid.\n * @param index - The index to validate.\n * @param array - The array to validate against.\n * @param apiName - The name of the API performing the validation.\n * @param allowOnePastEnd - Whether to allow the index to be one past the end of the array.\n */\nexport function validateIndex(\n\tindex: number,\n\tarray: { readonly length: number },\n\tapiName: string,\n\tallowOnePastEnd: boolean = false,\n): void {\n\tvalidatePositiveIndex(index, apiName);\n\tif (allowOnePastEnd) {\n\t\tif (index > array.length) {\n\t\t\tthrow new UsageError(\n\t\t\t\t`Index value passed to ${apiName} is out of bounds. Expected at most ${array.length}, got ${index}.`,\n\t\t\t);\n\t\t}\n\t} else {\n\t\tif (index >= array.length) {\n\t\t\tthrow new UsageError(\n\t\t\t\t`Index value passed to ${apiName} is out of bounds. Expected at most ${array.length - 1}, got ${index}.`,\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * Validates that the provided range `[startIndex, endIndex)` is valid and within the bounds of the provided array.\n * @remarks\n * This is intended for ranges which are inclusive for the lower bound, and exclusive for the upper bound,\n * and permits 0 length ranges, even `[array.length, array.length)`.\n * @throws If the index is invalid.\n * @param startIndex - The index that starts the range (inclusive).\n * @param endIndex - The index that ends the range (exclusive).\n * @param array - The array to validate against.\n * @param apiName - The name of the API performing the validation.\n */\nexport function validateIndexRange(\n\tstartIndex: number,\n\tendIndex: number,\n\tarray: { readonly length: number },\n\tapiName: string,\n): void {\n\tif (startIndex > endIndex) {\n\t\tthrow new UsageError(\n\t\t\t`Malformed range passed to ${apiName}. Start index ${startIndex} is greater than end index ${endIndex}.`,\n\t\t);\n\t}\n\tvalidateIndex(startIndex, array, apiName, true);\n\tvalidateIndex(endIndex, array, apiName, true);\n}\n"]}
1
+ {"version":3,"file":"arrayUtilities.js","sourceRoot":"","sources":["../../src/util/arrayUtilities.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAC;AAEtE;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAa,EAAE,OAAe;IACjE,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,UAAU,CAAC,qCAAqC,OAAO,SAAS,KAAK,GAAG,CAAC,CAAC;IACrF,CAAC;AACF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAa,EAAE,OAAe;IACnE,mBAAmB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACpC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACf,MAAM,IAAI,UAAU,CAAC,yCAAyC,OAAO,SAAS,KAAK,GAAG,CAAC,CAAC;IACzF,CAAC;AACF,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAC5B,KAAa,EACb,KAAkC,EAClC,OAAe,EACf,kBAA2B,KAAK;IAEhC,qBAAqB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACtC,IAAI,eAAe,EAAE,CAAC;QACrB,IAAI,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YAC1B,MAAM,IAAI,UAAU,CACnB,yBAAyB,OAAO,uCAAuC,KAAK,CAAC,MAAM,SAAS,KAAK,GAAG,CACpG,CAAC;QACH,CAAC;IACF,CAAC;SAAM,CAAC;QACP,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YAC3B,MAAM,IAAI,UAAU,CACnB,yBAAyB,OAAO,uCAAuC,KAAK,CAAC,MAAM,GAAG,CAAC,SAAS,KAAK,GAAG,CACxG,CAAC;QACH,CAAC;IACF,CAAC;AACF,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,kBAAkB,CACjC,UAAkB,EAClB,QAAgB,EAChB,KAAkC,EAClC,OAAe;IAEf,IAAI,UAAU,GAAG,QAAQ,EAAE,CAAC;QAC3B,MAAM,IAAI,UAAU,CACnB,6BAA6B,OAAO,iBAAiB,UAAU,8BAA8B,QAAQ,GAAG,CACxG,CAAC;IACH,CAAC;IACD,aAAa,CAAC,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAChD,aAAa,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;AAC/C,CAAC;AAYD;;;;;;GAMG;AACH,MAAM,UAAU,uBAAuB,CACtC,KAA+D,EAC/D,aAAmC;IAEnC,MAAM,MAAM,GAAqC,EAAE,CAAC;IACpD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,IAAI,aAAa,CAAC,KAAK,CAAC,CAAC,CAAM,CAAC,EAAE,CAAC;YAClC,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACvC,IAAI,IAAI,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;gBACrB,IAAI,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;YAClB,CAAC;iBAAM,CAAC;gBACP,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACvC,CAAC;QACF,CAAC;IACF,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { UsageError } from \"@fluidframework/telemetry-utils/internal\";\n\n/**\n * Validates that the provided index is a safe integer.\n * @throws If the index is invalid.\n * @param index - The index to validate.\n * @param apiName - The name of the API performing the validation.\n * @throws If the index is invalid.\n */\nexport function validateSafeInteger(index: number, apiName: string): void {\n\tif (!Number.isSafeInteger(index)) {\n\t\tthrow new UsageError(`Expected a safe integer passed to ${apiName}, got ${index}.`);\n\t}\n}\n\n/**\n * Validates that the provided index is a 0 or greater safe integer.\n * @param index - The index to validate.\n * @param apiName - The name of the API performing the validation.\n * @throws If the index is invalid.\n */\nexport function validatePositiveIndex(index: number, apiName: string): void {\n\tvalidateSafeInteger(index, apiName);\n\tif (index < 0) {\n\t\tthrow new UsageError(`Expected non-negative index passed to ${apiName}, got ${index}.`);\n\t}\n}\n\n/**\n * Validates that the provided index is a non-negative safe integer within the bounds of the provided array (or, optionally, 1 past its end).\n * @throws If the index is invalid.\n * @param index - The index to validate.\n * @param array - The array to validate against.\n * @param apiName - The name of the API performing the validation.\n * @param allowOnePastEnd - Whether to allow the index to be one past the end of the array.\n */\nexport function validateIndex(\n\tindex: number,\n\tarray: { readonly length: number },\n\tapiName: string,\n\tallowOnePastEnd: boolean = false,\n): void {\n\tvalidatePositiveIndex(index, apiName);\n\tif (allowOnePastEnd) {\n\t\tif (index > array.length) {\n\t\t\tthrow new UsageError(\n\t\t\t\t`Index value passed to ${apiName} is out of bounds. Expected at most ${array.length}, got ${index}.`,\n\t\t\t);\n\t\t}\n\t} else {\n\t\tif (index >= array.length) {\n\t\t\tthrow new UsageError(\n\t\t\t\t`Index value passed to ${apiName} is out of bounds. Expected at most ${array.length - 1}, got ${index}.`,\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * Validates that the provided range `[startIndex, endIndex)` is valid and within the bounds of the provided array.\n * @remarks\n * This is intended for ranges which are inclusive for the lower bound, and exclusive for the upper bound,\n * and permits 0 length ranges, even `[array.length, array.length)`.\n * @throws If the index is invalid.\n * @param startIndex - The index that starts the range (inclusive).\n * @param endIndex - The index that ends the range (exclusive).\n * @param array - The array to validate against.\n * @param apiName - The name of the API performing the validation.\n */\nexport function validateIndexRange(\n\tstartIndex: number,\n\tendIndex: number,\n\tarray: { readonly length: number },\n\tapiName: string,\n): void {\n\tif (startIndex > endIndex) {\n\t\tthrow new UsageError(\n\t\t\t`Malformed range passed to ${apiName}. Start index ${startIndex} is greater than end index ${endIndex}.`,\n\t\t);\n\t}\n\tvalidateIndex(startIndex, array, apiName, true);\n\tvalidateIndex(endIndex, array, apiName, true);\n}\n\n/**\n * A half-open `[start, end)` range of array indices.\n */\nexport interface IndexRange {\n\t/** Start index, inclusive. */\n\treadonly start: number;\n\t/** End index, exclusive. */\n\treadonly end: number;\n}\n\n/**\n * Walks `array` in order and collects the indices of every element for which `predicate` returns\n * `true` into contiguous `[start, end)` ranges.\n * @param array - The array (or array-like) to scan.\n * @param shouldInclude - Returns `true` for elements whose indices should be included.\n * @returns The collected ranges in ascending order. The returned array is empty if no elements match.\n */\nexport function collectContiguousRanges<T>(\n\tarray: { readonly length: number; readonly [index: number]: T },\n\tshouldInclude: (item: T) => boolean,\n): readonly IndexRange[] {\n\tconst ranges: { start: number; end: number }[] = [];\n\tfor (let i = 0; i < array.length; i++) {\n\t\tif (shouldInclude(array[i] as T)) {\n\t\t\tconst last = ranges[ranges.length - 1];\n\t\t\tif (last?.end === i) {\n\t\t\t\tlast.end = i + 1;\n\t\t\t} else {\n\t\t\t\tranges.push({ start: i, end: i + 1 });\n\t\t\t}\n\t\t}\n\t}\n\treturn ranges;\n}\n"]}
@@ -2,7 +2,7 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- export { validateIndex, validateIndexRange, validatePositiveIndex, validateSafeInteger, } from "./arrayUtilities.js";
5
+ export { collectContiguousRanges, type IndexRange, validateIndex, validateIndexRange, validatePositiveIndex, validateSafeInteger, } from "./arrayUtilities.js";
6
6
  export { brand, type Brand, BrandedType, type NameFromBranded, type ValueFromBranded, brandConst, type Values, strictEnum, unbrand, } from "./brand.js";
7
7
  export { brandedNumberType, brandedStringType } from "./typeboxBrand.js";
8
8
  export { brandOpaque, extractFromOpaque, type ExtractFromOpaque, type Opaque, } from "./opaque.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/util/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/util/index.ts"],"names":[],"mappings":"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"}
package/lib/util/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- export { validateIndex, validateIndexRange, validatePositiveIndex, validateSafeInteger, } from "./arrayUtilities.js";
5
+ export { collectContiguousRanges, validateIndex, validateIndexRange, validatePositiveIndex, validateSafeInteger, } from "./arrayUtilities.js";
6
6
  export { brand, BrandedType, brandConst, strictEnum, unbrand, } from "./brand.js";
7
7
  export { brandedNumberType, brandedStringType } from "./typeboxBrand.js";
8
8
  export { brandOpaque, extractFromOpaque, } from "./opaque.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/util/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,aAAa,EACb,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,GACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACN,KAAK,EAEL,WAAW,EAGX,UAAU,EAEV,UAAU,EACV,OAAO,GACP,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EACN,WAAW,EACX,iBAAiB,GAGjB,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,EACvB,kBAAkB,EAGlB,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,GACtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,cAAc,EAAkB,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnF,OAAO,EAAmB,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAiBrE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EACN,SAAS,EACT,cAAc,EACd,WAAW,EACX,kBAAkB,EAClB,WAAW,EACX,YAAY,EACZ,eAAe,EAKf,4BAA4B,EAC5B,SAAS,EACT,WAAW,EACX,cAAc,EAId,gBAAgB,EAChB,gBAAgB,EAChB,4BAA4B,EAC5B,WAAW,EACX,SAAS,EACT,eAAe,EACf,aAAa,EAEb,UAAU,EACV,uBAAuB,EACvB,kBAAkB,EAClB,cAAc,EACd,qBAAqB,EACrB,cAAc,EACd,qBAAqB,EACrB,IAAI,EACJ,KAAK,EACL,OAAO,EACP,OAAO,EACP,SAAS,EACT,wBAAwB,EACxB,qBAAqB,IAAI,YAAY,EACrC,aAAa,EACb,eAAe,GACf,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAyB,MAAM,wBAAwB,CAAC;AAcrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEpD,OAAO,EAIN,sBAAsB,EACtB,WAAW,GACX,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACN,QAAQ,EAER,kBAAkB,GAClB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAEN,oBAAoB,EACpB,oBAAoB,EAEpB,eAAe,GACf,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACN,SAAS,EAET,cAAc,EACd,aAAa,EACb,aAAa,GACb,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAEN,aAAa,EACb,gBAAgB,EAChB,qBAAqB,GACrB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport {\n\tvalidateIndex,\n\tvalidateIndexRange,\n\tvalidatePositiveIndex,\n\tvalidateSafeInteger,\n} from \"./arrayUtilities.js\";\nexport {\n\tbrand,\n\ttype Brand,\n\tBrandedType,\n\ttype NameFromBranded,\n\ttype ValueFromBranded,\n\tbrandConst,\n\ttype Values,\n\tstrictEnum,\n\tunbrand,\n} from \"./brand.js\";\nexport { brandedNumberType, brandedStringType } from \"./typeboxBrand.js\";\nexport {\n\tbrandOpaque,\n\textractFromOpaque,\n\ttype ExtractFromOpaque,\n\ttype Opaque,\n} from \"./opaque.js\";\nexport {\n\tdeleteFromNestedMap,\n\tgetOrAddInNestedMap,\n\tgetOrDefaultInNestedMap,\n\tforEachInNestedMap,\n\ttype NestedMap,\n\ttype ReadonlyNestedMap,\n\tSizedNestedMap,\n\tpopulateNestedMap,\n\tsetInNestedMap,\n\ttryAddToNestedMap,\n\ttryGetFromNestedMap,\n\tmapNestedMap,\n\tnestedMapToFlatList,\n\tnestedMapFromFlatList,\n\tgetOrCreateInNestedMap,\n} from \"./nestedMap.js\";\nexport { addToNestedSet, type NestedSet, nestedSetContains } from \"./nestedSet.js\";\nexport { type OffsetList, OffsetListFactory } from \"./offsetList.js\";\nexport type {\n\tareSafelyAssignable,\n\tContravariant,\n\tCovariant,\n\teitherIsAny,\n\tEnforceTypeCheckTests,\n\tInvariant,\n\tisAny,\n\tisAssignableTo,\n\tisStrictSubset,\n\tMakeNominal,\n\trequireFalse,\n\trequireTrue,\n\trequireAssignableTo,\n\tareOnlyKeys,\n} from \"./typeCheck.js\";\nexport { StackyIterator } from \"./stackyIterator.js\";\nexport {\n\tasMutable,\n\tbalancedReduce,\n\tcompareSets,\n\tgetOrAddEmptyToMap,\n\tgetOrCreate,\n\tisJsonObject,\n\tisReadonlyArray,\n\ttype JsonCompatible,\n\ttype JsonCompatibleObject,\n\ttype JsonCompatibleReadOnly,\n\ttype JsonCompatibleReadOnlyObject,\n\tJsonCompatibleReadOnlySchema,\n\tmakeArray,\n\tmapIterable,\n\tfilterIterable,\n\ttype Mutable,\n\ttype Populated,\n\ttype RecursiveReadonly,\n\tassertValidIndex,\n\tassertValidRange,\n\tassertNonNegativeSafeInteger,\n\tobjectToMap,\n\tinvertMap,\n\toneFromIterable,\n\tdisposeSymbol,\n\ttype IDisposable,\n\tcapitalize,\n\tassertValidRangeIndices,\n\ttransformObjectMap,\n\tcompareNumbers,\n\tcomparePartialNumbers,\n\tcompareStrings,\n\tcomparePartialStrings,\n\tfind,\n\tcount,\n\tgetLast,\n\thasSome,\n\thasSingle,\n\tdefineLazyCachedProperty,\n\tcopyPropertyIfDefined as copyProperty,\n\tgetOrAddInMap,\n\titerableHasSome,\n} from \"./utils.js\";\nexport { ReferenceCountedBase, type ReferenceCounted } from \"./referenceCounting.js\";\n\nexport type {\n\t_RecursiveTrick,\n\tRestrictiveReadonlyRecord,\n\tRestrictiveStringRecord,\n\t_InlineTrick,\n\tFlattenKeys,\n\tIsUnion,\n\tUnionToIntersection,\n\tUnionToTuple,\n\tPopUnion,\n} from \"./typeUtils.js\";\n\nexport { unsafeArrayToTuple } from \"./typeUtils.js\";\n\nexport {\n\ttype BrandedKey,\n\ttype BrandedKeyContent,\n\ttype BrandedMapSubset,\n\tgetOrCreateSlotContent,\n\tbrandedSlot,\n} from \"./brandedMap.js\";\n\nexport {\n\tRangeMap,\n\ttype RangeQueryResult,\n\tnewIntegerRangeMap,\n} from \"./rangeMap.js\";\n\nexport {\n\ttype IdAllocator,\n\tidAllocatorFromMaxId,\n\tidAllocatorFromState,\n\ttype IdAllocationState,\n\tfakeIdAllocator,\n} from \"./idAllocator.js\";\n\nexport {\n\tBreakable,\n\ttype WithBreakable,\n\tbreakingMethod,\n\tthrowIfBroken,\n\tbreakingClass,\n} from \"./breakable.js\";\n\nexport {\n\ttype TupleBTree,\n\tnewTupleBTree,\n\tmergeTupleBTrees,\n\tcreateTupleComparator,\n} from \"./bTreeUtils.js\";\n\nexport { cloneWithReplacements } from \"./cloneWithReplacements.js\";\n\nexport { readAndParseSnapshotBlob } from \"./readSnapshotBlob.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/util/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,uBAAuB,EAEvB,aAAa,EACb,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,GACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACN,KAAK,EAEL,WAAW,EAGX,UAAU,EAEV,UAAU,EACV,OAAO,GACP,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EACN,WAAW,EACX,iBAAiB,GAGjB,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,EACvB,kBAAkB,EAGlB,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,GACtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,cAAc,EAAkB,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnF,OAAO,EAAmB,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAiBrE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EACN,SAAS,EACT,cAAc,EACd,WAAW,EACX,kBAAkB,EAClB,WAAW,EACX,YAAY,EACZ,eAAe,EAKf,4BAA4B,EAC5B,SAAS,EACT,WAAW,EACX,cAAc,EAId,gBAAgB,EAChB,gBAAgB,EAChB,4BAA4B,EAC5B,WAAW,EACX,SAAS,EACT,eAAe,EACf,aAAa,EAEb,UAAU,EACV,uBAAuB,EACvB,kBAAkB,EAClB,cAAc,EACd,qBAAqB,EACrB,cAAc,EACd,qBAAqB,EACrB,IAAI,EACJ,KAAK,EACL,OAAO,EACP,OAAO,EACP,SAAS,EACT,wBAAwB,EACxB,qBAAqB,IAAI,YAAY,EACrC,aAAa,EACb,eAAe,GACf,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAyB,MAAM,wBAAwB,CAAC;AAcrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEpD,OAAO,EAIN,sBAAsB,EACtB,WAAW,GACX,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACN,QAAQ,EAER,kBAAkB,GAClB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAEN,oBAAoB,EACpB,oBAAoB,EAEpB,eAAe,GACf,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACN,SAAS,EAET,cAAc,EACd,aAAa,EACb,aAAa,GACb,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAEN,aAAa,EACb,gBAAgB,EAChB,qBAAqB,GACrB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport {\n\tcollectContiguousRanges,\n\ttype IndexRange,\n\tvalidateIndex,\n\tvalidateIndexRange,\n\tvalidatePositiveIndex,\n\tvalidateSafeInteger,\n} from \"./arrayUtilities.js\";\nexport {\n\tbrand,\n\ttype Brand,\n\tBrandedType,\n\ttype NameFromBranded,\n\ttype ValueFromBranded,\n\tbrandConst,\n\ttype Values,\n\tstrictEnum,\n\tunbrand,\n} from \"./brand.js\";\nexport { brandedNumberType, brandedStringType } from \"./typeboxBrand.js\";\nexport {\n\tbrandOpaque,\n\textractFromOpaque,\n\ttype ExtractFromOpaque,\n\ttype Opaque,\n} from \"./opaque.js\";\nexport {\n\tdeleteFromNestedMap,\n\tgetOrAddInNestedMap,\n\tgetOrDefaultInNestedMap,\n\tforEachInNestedMap,\n\ttype NestedMap,\n\ttype ReadonlyNestedMap,\n\tSizedNestedMap,\n\tpopulateNestedMap,\n\tsetInNestedMap,\n\ttryAddToNestedMap,\n\ttryGetFromNestedMap,\n\tmapNestedMap,\n\tnestedMapToFlatList,\n\tnestedMapFromFlatList,\n\tgetOrCreateInNestedMap,\n} from \"./nestedMap.js\";\nexport { addToNestedSet, type NestedSet, nestedSetContains } from \"./nestedSet.js\";\nexport { type OffsetList, OffsetListFactory } from \"./offsetList.js\";\nexport type {\n\tareSafelyAssignable,\n\tContravariant,\n\tCovariant,\n\teitherIsAny,\n\tEnforceTypeCheckTests,\n\tInvariant,\n\tisAny,\n\tisAssignableTo,\n\tisStrictSubset,\n\tMakeNominal,\n\trequireFalse,\n\trequireTrue,\n\trequireAssignableTo,\n\tareOnlyKeys,\n} from \"./typeCheck.js\";\nexport { StackyIterator } from \"./stackyIterator.js\";\nexport {\n\tasMutable,\n\tbalancedReduce,\n\tcompareSets,\n\tgetOrAddEmptyToMap,\n\tgetOrCreate,\n\tisJsonObject,\n\tisReadonlyArray,\n\ttype JsonCompatible,\n\ttype JsonCompatibleObject,\n\ttype JsonCompatibleReadOnly,\n\ttype JsonCompatibleReadOnlyObject,\n\tJsonCompatibleReadOnlySchema,\n\tmakeArray,\n\tmapIterable,\n\tfilterIterable,\n\ttype Mutable,\n\ttype Populated,\n\ttype RecursiveReadonly,\n\tassertValidIndex,\n\tassertValidRange,\n\tassertNonNegativeSafeInteger,\n\tobjectToMap,\n\tinvertMap,\n\toneFromIterable,\n\tdisposeSymbol,\n\ttype IDisposable,\n\tcapitalize,\n\tassertValidRangeIndices,\n\ttransformObjectMap,\n\tcompareNumbers,\n\tcomparePartialNumbers,\n\tcompareStrings,\n\tcomparePartialStrings,\n\tfind,\n\tcount,\n\tgetLast,\n\thasSome,\n\thasSingle,\n\tdefineLazyCachedProperty,\n\tcopyPropertyIfDefined as copyProperty,\n\tgetOrAddInMap,\n\titerableHasSome,\n} from \"./utils.js\";\nexport { ReferenceCountedBase, type ReferenceCounted } from \"./referenceCounting.js\";\n\nexport type {\n\t_RecursiveTrick,\n\tRestrictiveReadonlyRecord,\n\tRestrictiveStringRecord,\n\t_InlineTrick,\n\tFlattenKeys,\n\tIsUnion,\n\tUnionToIntersection,\n\tUnionToTuple,\n\tPopUnion,\n} from \"./typeUtils.js\";\n\nexport { unsafeArrayToTuple } from \"./typeUtils.js\";\n\nexport {\n\ttype BrandedKey,\n\ttype BrandedKeyContent,\n\ttype BrandedMapSubset,\n\tgetOrCreateSlotContent,\n\tbrandedSlot,\n} from \"./brandedMap.js\";\n\nexport {\n\tRangeMap,\n\ttype RangeQueryResult,\n\tnewIntegerRangeMap,\n} from \"./rangeMap.js\";\n\nexport {\n\ttype IdAllocator,\n\tidAllocatorFromMaxId,\n\tidAllocatorFromState,\n\ttype IdAllocationState,\n\tfakeIdAllocator,\n} from \"./idAllocator.js\";\n\nexport {\n\tBreakable,\n\ttype WithBreakable,\n\tbreakingMethod,\n\tthrowIfBroken,\n\tbreakingClass,\n} from \"./breakable.js\";\n\nexport {\n\ttype TupleBTree,\n\tnewTupleBTree,\n\tmergeTupleBTrees,\n\tcreateTupleComparator,\n} from \"./bTreeUtils.js\";\n\nexport { cloneWithReplacements } from \"./cloneWithReplacements.js\";\n\nexport { readAndParseSnapshotBlob } from \"./readSnapshotBlob.js\";\n"]}
@@ -93,6 +93,19 @@ export declare class RangeMap<K, V> {
93
93
  * By default, `mergeFunc` chooses the value from `b`.
94
94
  */
95
95
  static union<K, V>(a: RangeMap<K, V>, b: RangeMap<K, V>, mergeFunc?: (key: K, valueA: V, valueB: V) => V): RangeMap<K, V>;
96
+ /**
97
+ * Calls provided handlers on intersecting portions of `mapA` and `mapB`.
98
+ * @param intersectionCallback - called once for each key range which has an entry in both `mapA` and `mapB`.
99
+ * @param residualCallback - called for each key range which only has an entry in one of the input maps,
100
+ * but which is part of a range entry that overlaps an entry in the other map.
101
+ * This may also be called for entries which are not part of an overlapping range.
102
+ */
103
+ private static forEachIntersection;
104
+ private static getOrNextEntry;
105
+ /**
106
+ * @returns a range entry representing the first defined key range greater than or equal to `key`.
107
+ */
108
+ private getOrNextEntry;
96
109
  private getIntersectingEntries;
97
110
  private gt;
98
111
  private ge;
@@ -1 +1 @@
1
- {"version":3,"file":"rangeMap.d.ts","sourceRoot":"","sources":["../../src/util/rangeMap.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH;;;;;;GAMG;AACH,qBAAa,QAAQ,CAAC,CAAC,EAAE,CAAC;aAqBR,SAAS,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;aACxC,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,MAAM;aACpC,WAAW,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;IAtB7D,OAAO,CAAC,IAAI,CAA0B;IAEtC;;;;;;;;;;;;;;;;OAgBG;gBAEc,SAAS,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC,EACxC,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,MAAM,EACpC,WAAW,GAAE,CAAC,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,KAAK,CAAwB;IAKpF;;OAEG;IACI,OAAO,IAAI,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;IAShC,KAAK,IAAI,IAAI;IAIpB;;;;;;;;OAQG;IACI,MAAM,CAAC,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,wBAAwB,CAAC,CAAC,GAAG,SAAS,CAAC,EAAE;IAclF;;;;;;;OAOG;IACI,QAAQ,CAAC,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAAC,CAAC,GAAG,SAAS,CAAC;IAqC1E;;;;;;OAMG;IACI,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,SAAS,GAAG,IAAI;IAOhE;;;;;;;;;;;;;;;;;;;;OAoBG;IACI,MAAM,CAAC,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM;IAgCxC,KAAK,IAAI,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC;IAM9B;;;;OAIG;WACW,KAAK,CAAC,CAAC,EAAE,CAAC,EACvB,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,EACjB,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,EACjB,SAAS,GAAE,CAAC,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,CAA0B,GACrE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC;IAuBjB,OAAO,CAAC,sBAAsB;IAkC9B,OAAO,CAAC,EAAE;IAIV,OAAO,CAAC,EAAE;IAIV,OAAO,CAAC,EAAE;IAIV,OAAO,CAAC,EAAE;CAGV;AAiBD;;GAEG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC;IAClC;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAElB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,wBAAwB,CAAC,CAAC,CAAE,SAAQ,gBAAgB,CAAC,CAAC,CAAC;IACvE;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,aAAa,CAAC,CAAC,EAAE,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAClB,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAClB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,KAAK,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAEjF"}
1
+ {"version":3,"file":"rangeMap.d.ts","sourceRoot":"","sources":["../../src/util/rangeMap.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,8 @@
4
4
  */
5
5
  import { assert } from "@fluidframework/core-utils/internal";
6
6
  import { BTree } from "@tylerbu/sorted-btree-es6";
7
+ // eslint-disable-next-line import-x/no-internal-modules
8
+ import { union } from "@tylerbu/sorted-btree-es6/extended/union";
7
9
  /**
8
10
  * RangeMap represents a mapping from keys of type K to values of type V or undefined.
9
11
  * The set of all possible keys is assumed to be fully ordered,
@@ -183,16 +185,75 @@ export class RangeMap {
183
185
  assert(a.offsetKey === b.offsetKey &&
184
186
  a.subtractKeys === b.subtractKeys &&
185
187
  a.offsetValue === b.offsetValue, 0xaae /* Maps should have the same behavior */);
186
- const merged = a.clone();
187
- for (const entryB of b.entries()) {
188
- for (const entryA of a.getAll(entryB.start, entryB.length)) {
189
- const key = b.offsetKey(entryB.start, entryA.offset);
190
- const valueB = b.offsetValue(entryB.value, entryA.offset);
191
- const mergedValue = entryA.value === undefined ? valueB : mergeFunc(key, entryA.value, valueB);
192
- merged.set(key, entryA.length, mergedValue);
188
+ const merged = new RangeMap(a.offsetKey, a.subtractKeys, a.offsetValue);
189
+ // We first union the underlying B-trees, possibly resulting in a malformed range map.
190
+ merged.tree = union(a.tree, b.tree, (key, v1, v2) => v1);
191
+ // We split the overlapping tree entries into ranges which are either fully overlapping (intersections),
192
+ // or fully non-overlapping (residuals).
193
+ // We create an entry for each of these ranges.
194
+ // After this, the merged map should be well-formed.
195
+ RangeMap.forEachIntersection(a, b, (key, length, valueA, valueB) => merged.tree.set(key, { value: mergeFunc(key, valueA, valueB), length }), (key, length, value) => merged.tree.set(key, { value, length }));
196
+ return merged;
197
+ }
198
+ /**
199
+ * Calls provided handlers on intersecting portions of `mapA` and `mapB`.
200
+ * @param intersectionCallback - called once for each key range which has an entry in both `mapA` and `mapB`.
201
+ * @param residualCallback - called for each key range which only has an entry in one of the input maps,
202
+ * but which is part of a range entry that overlaps an entry in the other map.
203
+ * This may also be called for entries which are not part of an overlapping range.
204
+ */
205
+ static forEachIntersection(mapA, mapB, intersectionCallback, residualCallback) {
206
+ let [entry1, map1, map2] = this.getOrNextEntry(mapA, mapB, undefined);
207
+ while (entry1 !== undefined) {
208
+ const entry2 = map2.getOrNextEntry(entry1.start);
209
+ if (entry2 !== undefined) {
210
+ // This is the number of keys in `entry1` that come before the first key in `entry2`.
211
+ const offset = Math.min(mapA.subtractKeys(entry2.start, entry1.start), entry1.length);
212
+ if (offset > 0) {
213
+ residualCallback(entry1.start, offset, entry1.value);
214
+ }
215
+ const intersectionLength = Math.min(entry1.length - offset, entry2.length);
216
+ if (intersectionLength > 0) {
217
+ const value1Offset = mapA.offsetValue(entry1.value, offset);
218
+ const [valueA, valueB] = map1 === mapA ? [value1Offset, entry2.value] : [entry2.value, value1Offset];
219
+ intersectionCallback(entry2.start, intersectionLength, valueA, valueB);
220
+ [entry1, map1, map2] = this.getOrNextEntry(mapA, mapB, mapA.offsetKey(entry2.start, intersectionLength));
221
+ continue;
222
+ }
193
223
  }
224
+ residualCallback(entry1.start, entry1.length, entry1.value);
225
+ [entry1, map1, map2] = this.getOrNextEntry(mapA, mapB, mapA.offsetKey(entry1.start, entry1.length));
194
226
  }
195
- return merged;
227
+ return;
228
+ }
229
+ static getOrNextEntry(mapA, mapB, key) {
230
+ const entryA = mapA.getOrNextEntry(key);
231
+ const entryB = mapB.getOrNextEntry(key);
232
+ if (entryA === undefined) {
233
+ return [entryB, mapB, mapA];
234
+ }
235
+ else if (entryB === undefined) {
236
+ return [entryA, mapA, mapB];
237
+ }
238
+ return mapA.le(entryA.start, entryB.start) ? [entryA, mapA, mapB] : [entryB, mapB, mapA];
239
+ }
240
+ /**
241
+ * @returns a range entry representing the first defined key range greater than or equal to `key`.
242
+ */
243
+ getOrNextEntry(minKey) {
244
+ const key = minKey ?? this.tree.minKey();
245
+ if (key === undefined) {
246
+ return undefined;
247
+ }
248
+ const result = this.getFirst(key, Infinity);
249
+ if (result.value !== undefined) {
250
+ return { start: key, value: result.value, length: result.length };
251
+ }
252
+ const entry = this.tree.nextHigherPair(key);
253
+ if (entry === undefined) {
254
+ return undefined;
255
+ }
256
+ return { start: entry[0], value: entry[1].value, length: entry[1].length };
196
257
  }
197
258
  getIntersectingEntries(start, length) {
198
259
  const entries = [];
@@ -1 +1 @@
1
- {"version":3,"file":"rangeMap.js","sourceRoot":"","sources":["../../src/util/rangeMap.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 { assert } from \"@fluidframework/core-utils/internal\";\nimport { BTree } from \"@tylerbu/sorted-btree-es6\";\n\n/**\n * RangeMap represents a mapping from keys of type K to values of type V or undefined.\n * The set of all possible keys is assumed to be fully ordered,\n * and for each key there should be a single next higher key.\n * The values for a range of consecutive keys can be changed or queried in a single operation.\n * The structure of the keys is described by the `offsetKey` and `subtractKeys` functions provided in the constructor.\n */\nexport class RangeMap<K, V> {\n\tprivate tree: BTree<K, RangeEntry<V>>;\n\n\t/**\n\t * @param offsetKey - Function which returns a new key which is `offset` keys after `key`.\n\t * When `offset` is negative, the returned key should come before `key`.\n\t *\n\t * @param subtractKeys - Function which returns the difference between `b` and `a`.\n\t * Offsetting `b` by this difference should return `a`.\n\t * The difference can be infinite if `a` cannot be reached from `b` by offsetting,\n\t * but the difference should still be positive if `a` is larger than `b` and negative if smaller.\n\t *\n\t * @param offsetValue - Function used to associate a range of values with a range of keys.\n\t * When writing to a range of keys starting with `start`, the value of the nth key is interpreted to be\n\t * `offsetValue(firstValue, n - 1)`.\n\t * The same logic should be used when interpreting the values for keys after the first in a\n\t * `RangeQueryResult` or `RangeMapEntry`.\n\t *\n\t * If `offsetValue` is left unspecified, all keys in a block will be given the same value.\n\t */\n\tpublic constructor(\n\t\tpublic readonly offsetKey: (key: K, offset: number) => K,\n\t\tpublic readonly subtractKeys: (a: K, b: K) => number,\n\t\tpublic readonly offsetValue: (value: V, offset: number) => V = defaultValueOffsetFn,\n\t) {\n\t\tthis.tree = new BTree(undefined, subtractKeys);\n\t}\n\n\t/**\n\t * Retrieves all entries from the RangeMap.\n\t */\n\tpublic entries(): RangeMapEntry<K, V>[] {\n\t\tconst entries: RangeMapEntry<K, V>[] = [];\n\t\tfor (const [start, entry] of this.tree.entries()) {\n\t\t\tentries.push({ start, length: entry.length, value: entry.value });\n\t\t}\n\n\t\treturn entries;\n\t}\n\n\tpublic clear(): void {\n\t\tthis.tree.clear();\n\t}\n\n\t/**\n\t * Retrieves the values for all keys in the query range.\n\t *\n\t * @param start - The first key in the range being queried\n\t * @param length - The length of the query range\n\t * @returns A list of fragments, each describing the value for a subrange of the query.\n\t * The fragments are in the same order as the keys.\n\t * The key for each fragment is `start` offset by `fragment.offset`.\n\t */\n\tpublic getAll(start: K, length: number): RangeQueryResultFragment<V | undefined>[] {\n\t\tlet offset = 0;\n\t\tconst results: RangeQueryResultFragment<V | undefined>[] = [];\n\n\t\twhile (offset < length) {\n\t\t\tconst key = this.offsetKey(start, offset);\n\t\t\tconst result = this.getFirst(key, length - offset);\n\t\t\tresults.push({ offset, value: result.value, length: result.length });\n\t\t\toffset += result.length;\n\t\t}\n\n\t\treturn results;\n\t}\n\n\t/**\n\t * Retrieves the value for some prefix of the query range.\n\t *\n\t * @param start - The first key in the query range.\n\t * @param length - The length of the query range.\n\t * @returns A RangeQueryResult containing the value associated with `start`,\n\t * and the number of consecutive keys with that same value (at least 1, at most `length`).\n\t */\n\tpublic getFirst(start: K, length: number): RangeQueryResult<V | undefined> {\n\t\t{\n\t\t\t// We first check for an entry with a key less than or equal to `start`.\n\t\t\tconst entry = this.tree.getPairOrNextLower(start);\n\t\t\tif (entry !== undefined) {\n\t\t\t\tconst entryKey = entry[0];\n\t\t\t\tconst { value, length: entryLength } = entry[1];\n\n\t\t\t\tconst entryLastKey = this.offsetKey(entryKey, entryLength - 1);\n\t\t\t\tconst lengthBeforeQuery = this.subtractKeys(start, entryKey);\n\t\t\t\tconst overlappingLength = Math.min(this.subtractKeys(entryLastKey, start) + 1, length);\n\t\t\t\tif (overlappingLength > 0) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tvalue: this.offsetValue(value, lengthBeforeQuery),\n\t\t\t\t\t\tlength: overlappingLength,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t{\n\t\t\t// There is no value associated with `start`.\n\t\t\t// Now we need to determine how many of the following keys are also undefined.\n\t\t\tconst key = this.tree.nextHigherKey(start);\n\t\t\tif (key !== undefined) {\n\t\t\t\tconst entryKey = key;\n\n\t\t\t\tconst lastQueryKey = this.offsetKey(start, length - 1);\n\t\t\t\tif (this.le(entryKey, lastQueryKey)) {\n\t\t\t\t\treturn { value: undefined, length: this.subtractKeys(entryKey, start) };\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn { value: undefined, length };\n\t\t}\n\t}\n\n\t/**\n\t * Sets the value for a specified range.\n\t *\n\t * @param start - The first key in the range being set.\n\t * @param length - The length of the range.\n\t * @param value - The value to associate with the range.\n\t */\n\tpublic set(start: K, length: number, value: V | undefined): void {\n\t\tthis.delete(start, length);\n\t\tif (value !== undefined) {\n\t\t\tthis.tree.set(start, { value, length });\n\t\t}\n\t}\n\n\t/**\n\t * Deletes values within a specified range, updating or removing existing entries.\n\t *\n\t * 1. If an entry is completely included in the deletion range, the whole entry will be deleted\n\t * e.g.: map = [[1, 2], [4, 6]], delete range: [3, 6]\n\t * map becomes [[1, 2]] after deletion\n\t * (Note: the notation [a, b] represents start = a, end = b for simpler visualization, instead of `b`\n\t * representing the length)\n\t *\n\t * 2. If an entry is partially overlapped with the deletion range, the start or end point will be shifted\n\t * e.g.: map = [[1, 2], [4, 6]], delete range: [2, 4]\n\t * map becomes [[1, 1], [5, 6]] after deletion\n\t *\n\t * 3. If an entry completely includes the deletion range, the original entry may be split into two.\n\t * e.g.: map = [[1, 6]], delete range: [2, 4]\n\t * map becomes [[1, 1], [5, 6]]\n\t *\n\t * @param start - The start of the range to delete (inclusive).\n\t * @param length - The length of the range to delete.\n\t * @returns The number of keys/value pairs deleted (integer between 0 and `length`, inclusive).\n\t */\n\tpublic delete(start: K, length: number): number {\n\t\tlet deleteCount = 0;\n\t\tconst lastDeleteKey = this.offsetKey(start, length - 1);\n\t\tfor (const { start: key, length: entryLength, value } of this.getIntersectingEntries(\n\t\t\tstart,\n\t\t\tlength,\n\t\t)) {\n\t\t\tdeleteCount += entryLength;\n\t\t\tthis.tree.delete(key);\n\t\t\tconst lengthBefore = this.subtractKeys(start, key);\n\t\t\tif (lengthBefore > 0) {\n\t\t\t\t// A portion of this entry comes before the deletion range, so we reinsert that portion.\n\t\t\t\tthis.tree.set(key, { length: lengthBefore, value });\n\t\t\t\tdeleteCount -= lengthBefore;\n\t\t\t}\n\n\t\t\tconst lastEntryKey = this.offsetKey(key, entryLength - 1);\n\t\t\tconst lengthAfter = this.subtractKeys(lastEntryKey, lastDeleteKey);\n\t\t\tif (lengthAfter > 0) {\n\t\t\t\t// A portion of this entry comes after the deletion range, so we reinsert that portion.\n\t\t\t\tconst newKey = this.offsetKey(lastDeleteKey, 1);\n\t\t\t\tconst difference = this.subtractKeys(newKey, key);\n\t\t\t\tthis.tree.set(newKey, {\n\t\t\t\t\tlength: lengthAfter,\n\t\t\t\t\tvalue: this.offsetValue(value, difference),\n\t\t\t\t});\n\t\t\t\tdeleteCount -= lengthAfter;\n\t\t\t}\n\t\t}\n\t\treturn deleteCount;\n\t}\n\n\tpublic clone(): RangeMap<K, V> {\n\t\tconst cloned = new RangeMap<K, V>(this.offsetKey, this.subtractKeys, this.offsetValue);\n\t\tcloned.tree = this.tree.clone();\n\t\treturn cloned;\n\t}\n\n\t/**\n\t * Returns a new map which contains the entries from both input maps.\n\t * Whenever both maps contain entries for the same keys, the value is determined by calling `mergeFunc`.\n\t * By default, `mergeFunc` chooses the value from `b`.\n\t */\n\tpublic static union<K, V>(\n\t\ta: RangeMap<K, V>,\n\t\tb: RangeMap<K, V>,\n\t\tmergeFunc: (key: K, valueA: V, valueB: V) => V = (_k, _a, valB) => valB,\n\t): RangeMap<K, V> {\n\t\tassert(\n\t\t\ta.offsetKey === b.offsetKey &&\n\t\t\t\ta.subtractKeys === b.subtractKeys &&\n\t\t\t\ta.offsetValue === b.offsetValue,\n\t\t\t0xaae /* Maps should have the same behavior */,\n\t\t);\n\n\t\tconst merged = a.clone();\n\t\tfor (const entryB of b.entries()) {\n\t\t\tfor (const entryA of a.getAll(entryB.start, entryB.length)) {\n\t\t\t\tconst key = b.offsetKey(entryB.start, entryA.offset);\n\t\t\t\tconst valueB = b.offsetValue(entryB.value, entryA.offset);\n\t\t\t\tconst mergedValue =\n\t\t\t\t\tentryA.value === undefined ? valueB : mergeFunc(key, entryA.value, valueB);\n\n\t\t\t\tmerged.set(key, entryA.length, mergedValue);\n\t\t\t}\n\t\t}\n\n\t\treturn merged;\n\t}\n\n\tprivate getIntersectingEntries(start: K, length: number): RangeMapEntry<K, V>[] {\n\t\tconst entries: RangeMapEntry<K, V>[] = [];\n\t\tconst lastQueryKey = this.offsetKey(start, length - 1);\n\t\t{\n\t\t\tconst entry = this.tree.getPairOrNextLower(start);\n\t\t\tif (entry !== undefined) {\n\t\t\t\tconst key = entry[0];\n\t\t\t\tconst { length: entryLength, value } = entry[1];\n\t\t\t\tconst lastEntryKey = this.offsetKey(key, entryLength - 1);\n\t\t\t\tif (this.ge(lastEntryKey, start)) {\n\t\t\t\t\tentries.push({ start: key, length: entryLength, value });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t{\n\t\t\tlet entry = this.tree.nextHigherPair(start);\n\t\t\twhile (entry !== undefined) {\n\t\t\t\tconst key = entry[0];\n\t\t\t\tif (this.gt(key, lastQueryKey)) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tconst { length: entryLength, value } = entry[1];\n\t\t\t\tconst lastEntryKey = this.offsetKey(key, entryLength - 1);\n\n\t\t\t\tentries.push({ start: key, length: entryLength, value });\n\t\t\t\tentry = this.tree.nextHigherPair(lastEntryKey);\n\t\t\t}\n\t\t}\n\n\t\treturn entries;\n\t}\n\n\tprivate gt(a: K, b: K): boolean {\n\t\treturn this.subtractKeys(a, b) > 0;\n\t}\n\n\tprivate ge(a: K, b: K): boolean {\n\t\treturn this.subtractKeys(a, b) >= 0;\n\t}\n\n\tprivate lt(a: K, b: K): boolean {\n\t\treturn this.subtractKeys(a, b) < 0;\n\t}\n\n\tprivate le(a: K, b: K): boolean {\n\t\treturn this.subtractKeys(a, b) <= 0;\n\t}\n}\n\n/**\n * Represents a contiguous range of values in the RangeMap.\n */\ninterface RangeEntry<V> {\n\t/**\n\t * The length of the range.\n\t */\n\treadonly length: number;\n\n\t/**\n\t * The value associated with this range.\n\t */\n\treadonly value: V;\n}\n\n/**\n * Describes the result of a range query, including the value and length of the matching prefix.\n */\nexport interface RangeQueryResult<V> {\n\t/**\n\t * The value of the first key in the query range.\n\t */\n\treadonly value: V;\n\n\t/**\n\t * The length of the prefix of the query range which has the same value.\n\t * For example, if a RangeMap has the same value for keys 5, 6, and 7,\n\t * a query about the range [5, 10] would give a result with length 3.\n\t */\n\treadonly length: number;\n}\n\nexport interface RangeQueryResultFragment<V> extends RangeQueryResult<V> {\n\t/**\n\t * The offset from the query key to the key this result is associated with.\n\t * This is useful in the case where a query returns multiple `RangeQueryResults`\n\t * addressing the key range.\n\t */\n\treadonly offset: number;\n}\n\nexport interface RangeMapEntry<K, V> {\n\treadonly start: K;\n\treadonly value: V;\n\treadonly length: number;\n}\n\nexport function newIntegerRangeMap<V, K extends number = number>(): RangeMap<K, V> {\n\treturn new RangeMap(offsetInteger, subtractIntegers);\n}\n\nfunction offsetInteger<K extends number>(key: K, offset: number): K {\n\treturn (key + offset) as K;\n}\n\nfunction subtractIntegers<K extends number>(a: K, b: K): number {\n\treturn a - b;\n}\n\nfunction defaultValueOffsetFn<T>(value: T, offset: number): T {\n\treturn value;\n}\n"]}
1
+ {"version":3,"file":"rangeMap.js","sourceRoot":"","sources":["../../src/util/rangeMap.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 { assert } from \"@fluidframework/core-utils/internal\";\nimport { BTree } from \"@tylerbu/sorted-btree-es6\";\n// eslint-disable-next-line import-x/no-internal-modules\nimport { union } from \"@tylerbu/sorted-btree-es6/extended/union\";\n\n/**\n * RangeMap represents a mapping from keys of type K to values of type V or undefined.\n * The set of all possible keys is assumed to be fully ordered,\n * and for each key there should be a single next higher key.\n * The values for a range of consecutive keys can be changed or queried in a single operation.\n * The structure of the keys is described by the `offsetKey` and `subtractKeys` functions provided in the constructor.\n */\nexport class RangeMap<K, V> {\n\tprivate tree: BTree<K, RangeEntry<V>>;\n\n\t/**\n\t * @param offsetKey - Function which returns a new key which is `offset` keys after `key`.\n\t * When `offset` is negative, the returned key should come before `key`.\n\t *\n\t * @param subtractKeys - Function which returns the difference between `b` and `a`.\n\t * Offsetting `b` by this difference should return `a`.\n\t * The difference can be infinite if `a` cannot be reached from `b` by offsetting,\n\t * but the difference should still be positive if `a` is larger than `b` and negative if smaller.\n\t *\n\t * @param offsetValue - Function used to associate a range of values with a range of keys.\n\t * When writing to a range of keys starting with `start`, the value of the nth key is interpreted to be\n\t * `offsetValue(firstValue, n - 1)`.\n\t * The same logic should be used when interpreting the values for keys after the first in a\n\t * `RangeQueryResult` or `RangeMapEntry`.\n\t *\n\t * If `offsetValue` is left unspecified, all keys in a block will be given the same value.\n\t */\n\tpublic constructor(\n\t\tpublic readonly offsetKey: (key: K, offset: number) => K,\n\t\tpublic readonly subtractKeys: (a: K, b: K) => number,\n\t\tpublic readonly offsetValue: (value: V, offset: number) => V = defaultValueOffsetFn,\n\t) {\n\t\tthis.tree = new BTree(undefined, subtractKeys);\n\t}\n\n\t/**\n\t * Retrieves all entries from the RangeMap.\n\t */\n\tpublic entries(): RangeMapEntry<K, V>[] {\n\t\tconst entries: RangeMapEntry<K, V>[] = [];\n\t\tfor (const [start, entry] of this.tree.entries()) {\n\t\t\tentries.push({ start, length: entry.length, value: entry.value });\n\t\t}\n\n\t\treturn entries;\n\t}\n\n\tpublic clear(): void {\n\t\tthis.tree.clear();\n\t}\n\n\t/**\n\t * Retrieves the values for all keys in the query range.\n\t *\n\t * @param start - The first key in the range being queried\n\t * @param length - The length of the query range\n\t * @returns A list of fragments, each describing the value for a subrange of the query.\n\t * The fragments are in the same order as the keys.\n\t * The key for each fragment is `start` offset by `fragment.offset`.\n\t */\n\tpublic getAll(start: K, length: number): RangeQueryResultFragment<V | undefined>[] {\n\t\tlet offset = 0;\n\t\tconst results: RangeQueryResultFragment<V | undefined>[] = [];\n\n\t\twhile (offset < length) {\n\t\t\tconst key = this.offsetKey(start, offset);\n\t\t\tconst result = this.getFirst(key, length - offset);\n\t\t\tresults.push({ offset, value: result.value, length: result.length });\n\t\t\toffset += result.length;\n\t\t}\n\n\t\treturn results;\n\t}\n\n\t/**\n\t * Retrieves the value for some prefix of the query range.\n\t *\n\t * @param start - The first key in the query range.\n\t * @param length - The length of the query range.\n\t * @returns A RangeQueryResult containing the value associated with `start`,\n\t * and the number of consecutive keys with that same value (at least 1, at most `length`).\n\t */\n\tpublic getFirst(start: K, length: number): RangeQueryResult<V | undefined> {\n\t\t{\n\t\t\t// We first check for an entry with a key less than or equal to `start`.\n\t\t\tconst entry = this.tree.getPairOrNextLower(start);\n\t\t\tif (entry !== undefined) {\n\t\t\t\tconst entryKey = entry[0];\n\t\t\t\tconst { value, length: entryLength } = entry[1];\n\n\t\t\t\tconst entryLastKey = this.offsetKey(entryKey, entryLength - 1);\n\t\t\t\tconst lengthBeforeQuery = this.subtractKeys(start, entryKey);\n\t\t\t\tconst overlappingLength = Math.min(this.subtractKeys(entryLastKey, start) + 1, length);\n\t\t\t\tif (overlappingLength > 0) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tvalue: this.offsetValue(value, lengthBeforeQuery),\n\t\t\t\t\t\tlength: overlappingLength,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t{\n\t\t\t// There is no value associated with `start`.\n\t\t\t// Now we need to determine how many of the following keys are also undefined.\n\t\t\tconst key = this.tree.nextHigherKey(start);\n\t\t\tif (key !== undefined) {\n\t\t\t\tconst entryKey = key;\n\n\t\t\t\tconst lastQueryKey = this.offsetKey(start, length - 1);\n\t\t\t\tif (this.le(entryKey, lastQueryKey)) {\n\t\t\t\t\treturn { value: undefined, length: this.subtractKeys(entryKey, start) };\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn { value: undefined, length };\n\t\t}\n\t}\n\n\t/**\n\t * Sets the value for a specified range.\n\t *\n\t * @param start - The first key in the range being set.\n\t * @param length - The length of the range.\n\t * @param value - The value to associate with the range.\n\t */\n\tpublic set(start: K, length: number, value: V | undefined): void {\n\t\tthis.delete(start, length);\n\t\tif (value !== undefined) {\n\t\t\tthis.tree.set(start, { value, length });\n\t\t}\n\t}\n\n\t/**\n\t * Deletes values within a specified range, updating or removing existing entries.\n\t *\n\t * 1. If an entry is completely included in the deletion range, the whole entry will be deleted\n\t * e.g.: map = [[1, 2], [4, 6]], delete range: [3, 6]\n\t * map becomes [[1, 2]] after deletion\n\t * (Note: the notation [a, b] represents start = a, end = b for simpler visualization, instead of `b`\n\t * representing the length)\n\t *\n\t * 2. If an entry is partially overlapped with the deletion range, the start or end point will be shifted\n\t * e.g.: map = [[1, 2], [4, 6]], delete range: [2, 4]\n\t * map becomes [[1, 1], [5, 6]] after deletion\n\t *\n\t * 3. If an entry completely includes the deletion range, the original entry may be split into two.\n\t * e.g.: map = [[1, 6]], delete range: [2, 4]\n\t * map becomes [[1, 1], [5, 6]]\n\t *\n\t * @param start - The start of the range to delete (inclusive).\n\t * @param length - The length of the range to delete.\n\t * @returns The number of keys/value pairs deleted (integer between 0 and `length`, inclusive).\n\t */\n\tpublic delete(start: K, length: number): number {\n\t\tlet deleteCount = 0;\n\t\tconst lastDeleteKey = this.offsetKey(start, length - 1);\n\t\tfor (const { start: key, length: entryLength, value } of this.getIntersectingEntries(\n\t\t\tstart,\n\t\t\tlength,\n\t\t)) {\n\t\t\tdeleteCount += entryLength;\n\t\t\tthis.tree.delete(key);\n\t\t\tconst lengthBefore = this.subtractKeys(start, key);\n\t\t\tif (lengthBefore > 0) {\n\t\t\t\t// A portion of this entry comes before the deletion range, so we reinsert that portion.\n\t\t\t\tthis.tree.set(key, { length: lengthBefore, value });\n\t\t\t\tdeleteCount -= lengthBefore;\n\t\t\t}\n\n\t\t\tconst lastEntryKey = this.offsetKey(key, entryLength - 1);\n\t\t\tconst lengthAfter = this.subtractKeys(lastEntryKey, lastDeleteKey);\n\t\t\tif (lengthAfter > 0) {\n\t\t\t\t// A portion of this entry comes after the deletion range, so we reinsert that portion.\n\t\t\t\tconst newKey = this.offsetKey(lastDeleteKey, 1);\n\t\t\t\tconst difference = this.subtractKeys(newKey, key);\n\t\t\t\tthis.tree.set(newKey, {\n\t\t\t\t\tlength: lengthAfter,\n\t\t\t\t\tvalue: this.offsetValue(value, difference),\n\t\t\t\t});\n\t\t\t\tdeleteCount -= lengthAfter;\n\t\t\t}\n\t\t}\n\t\treturn deleteCount;\n\t}\n\n\tpublic clone(): RangeMap<K, V> {\n\t\tconst cloned = new RangeMap<K, V>(this.offsetKey, this.subtractKeys, this.offsetValue);\n\t\tcloned.tree = this.tree.clone();\n\t\treturn cloned;\n\t}\n\n\t/**\n\t * Returns a new map which contains the entries from both input maps.\n\t * Whenever both maps contain entries for the same keys, the value is determined by calling `mergeFunc`.\n\t * By default, `mergeFunc` chooses the value from `b`.\n\t */\n\tpublic static union<K, V>(\n\t\ta: RangeMap<K, V>,\n\t\tb: RangeMap<K, V>,\n\t\tmergeFunc: (key: K, valueA: V, valueB: V) => V = (_k, _a, valB) => valB,\n\t): RangeMap<K, V> {\n\t\tassert(\n\t\t\ta.offsetKey === b.offsetKey &&\n\t\t\t\ta.subtractKeys === b.subtractKeys &&\n\t\t\t\ta.offsetValue === b.offsetValue,\n\t\t\t0xaae /* Maps should have the same behavior */,\n\t\t);\n\n\t\tconst merged = new RangeMap<K, V>(a.offsetKey, a.subtractKeys, a.offsetValue);\n\n\t\t// We first union the underlying B-trees, possibly resulting in a malformed range map.\n\t\tmerged.tree = union<BTree<K, RangeEntry<V>>, K, RangeEntry<V>>(\n\t\t\ta.tree,\n\t\t\tb.tree,\n\t\t\t(key, v1, v2) => v1,\n\t\t);\n\n\t\t// We split the overlapping tree entries into ranges which are either fully overlapping (intersections),\n\t\t// or fully non-overlapping (residuals).\n\t\t// We create an entry for each of these ranges.\n\t\t// After this, the merged map should be well-formed.\n\t\tRangeMap.forEachIntersection(\n\t\t\ta,\n\t\t\tb,\n\t\t\t(key, length, valueA, valueB) =>\n\t\t\t\tmerged.tree.set(key, { value: mergeFunc(key, valueA, valueB), length }),\n\t\t\t(key, length, value) => merged.tree.set(key, { value, length }),\n\t\t);\n\n\t\treturn merged;\n\t}\n\n\t/**\n\t * Calls provided handlers on intersecting portions of `mapA` and `mapB`.\n\t * @param intersectionCallback - called once for each key range which has an entry in both `mapA` and `mapB`.\n\t * @param residualCallback - called for each key range which only has an entry in one of the input maps,\n\t * but which is part of a range entry that overlaps an entry in the other map.\n\t * This may also be called for entries which are not part of an overlapping range.\n\t */\n\tprivate static forEachIntersection<K, V>(\n\t\tmapA: RangeMap<K, V>,\n\t\tmapB: RangeMap<K, V>,\n\t\tintersectionCallback: (key: K, length: number, valueA: V, valueB: V) => void,\n\t\tresidualCallback: (key: K, length: number, value: V) => void,\n\t): void {\n\t\tlet [entry1, map1, map2] = this.getOrNextEntry(mapA, mapB, undefined);\n\t\twhile (entry1 !== undefined) {\n\t\t\tconst entry2 = map2.getOrNextEntry(entry1.start);\n\t\t\tif (entry2 !== undefined) {\n\t\t\t\t// This is the number of keys in `entry1` that come before the first key in `entry2`.\n\t\t\t\tconst offset = Math.min(mapA.subtractKeys(entry2.start, entry1.start), entry1.length);\n\t\t\t\tif (offset > 0) {\n\t\t\t\t\tresidualCallback(entry1.start, offset, entry1.value);\n\t\t\t\t}\n\n\t\t\t\tconst intersectionLength = Math.min(entry1.length - offset, entry2.length);\n\t\t\t\tif (intersectionLength > 0) {\n\t\t\t\t\tconst value1Offset = mapA.offsetValue(entry1.value, offset);\n\t\t\t\t\tconst [valueA, valueB] =\n\t\t\t\t\t\tmap1 === mapA ? [value1Offset, entry2.value] : [entry2.value, value1Offset];\n\n\t\t\t\t\tintersectionCallback(entry2.start, intersectionLength, valueA, valueB);\n\t\t\t\t\t[entry1, map1, map2] = this.getOrNextEntry(\n\t\t\t\t\t\tmapA,\n\t\t\t\t\t\tmapB,\n\t\t\t\t\t\tmapA.offsetKey(entry2.start, intersectionLength),\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tresidualCallback(entry1.start, entry1.length, entry1.value);\n\t\t\t[entry1, map1, map2] = this.getOrNextEntry(\n\t\t\t\tmapA,\n\t\t\t\tmapB,\n\t\t\t\tmapA.offsetKey(entry1.start, entry1.length),\n\t\t\t);\n\t\t}\n\n\t\treturn;\n\t}\n\n\tprivate static getOrNextEntry<K, V>(\n\t\tmapA: RangeMap<K, V>,\n\t\tmapB: RangeMap<K, V>,\n\t\tkey: K | undefined,\n\t): [RangeMapEntry<K, V> | undefined, firstMap: RangeMap<K, V>, secondMap: RangeMap<K, V>] {\n\t\tconst entryA = mapA.getOrNextEntry(key);\n\t\tconst entryB = mapB.getOrNextEntry(key);\n\t\tif (entryA === undefined) {\n\t\t\treturn [entryB, mapB, mapA];\n\t\t} else if (entryB === undefined) {\n\t\t\treturn [entryA, mapA, mapB];\n\t\t}\n\n\t\treturn mapA.le(entryA.start, entryB.start) ? [entryA, mapA, mapB] : [entryB, mapB, mapA];\n\t}\n\n\t/**\n\t * @returns a range entry representing the first defined key range greater than or equal to `key`.\n\t */\n\tprivate getOrNextEntry(minKey: K | undefined): RangeMapEntry<K, V> | undefined {\n\t\tconst key = minKey ?? this.tree.minKey();\n\t\tif (key === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst result = this.getFirst(key, Infinity);\n\t\tif (result.value !== undefined) {\n\t\t\treturn { start: key, value: result.value, length: result.length };\n\t\t}\n\n\t\tconst entry = this.tree.nextHigherPair(key);\n\t\tif (entry === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn { start: entry[0], value: entry[1].value, length: entry[1].length };\n\t}\n\n\tprivate getIntersectingEntries(start: K, length: number): RangeMapEntry<K, V>[] {\n\t\tconst entries: RangeMapEntry<K, V>[] = [];\n\t\tconst lastQueryKey = this.offsetKey(start, length - 1);\n\t\t{\n\t\t\tconst entry = this.tree.getPairOrNextLower(start);\n\t\t\tif (entry !== undefined) {\n\t\t\t\tconst key = entry[0];\n\t\t\t\tconst { length: entryLength, value } = entry[1];\n\t\t\t\tconst lastEntryKey = this.offsetKey(key, entryLength - 1);\n\t\t\t\tif (this.ge(lastEntryKey, start)) {\n\t\t\t\t\tentries.push({ start: key, length: entryLength, value });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t{\n\t\t\tlet entry = this.tree.nextHigherPair(start);\n\t\t\twhile (entry !== undefined) {\n\t\t\t\tconst key = entry[0];\n\t\t\t\tif (this.gt(key, lastQueryKey)) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tconst { length: entryLength, value } = entry[1];\n\t\t\t\tconst lastEntryKey = this.offsetKey(key, entryLength - 1);\n\n\t\t\t\tentries.push({ start: key, length: entryLength, value });\n\t\t\t\tentry = this.tree.nextHigherPair(lastEntryKey);\n\t\t\t}\n\t\t}\n\n\t\treturn entries;\n\t}\n\n\tprivate gt(a: K, b: K): boolean {\n\t\treturn this.subtractKeys(a, b) > 0;\n\t}\n\n\tprivate ge(a: K, b: K): boolean {\n\t\treturn this.subtractKeys(a, b) >= 0;\n\t}\n\n\tprivate lt(a: K, b: K): boolean {\n\t\treturn this.subtractKeys(a, b) < 0;\n\t}\n\n\tprivate le(a: K, b: K): boolean {\n\t\treturn this.subtractKeys(a, b) <= 0;\n\t}\n}\n\n/**\n * Represents a contiguous range of values in the RangeMap.\n */\ninterface RangeEntry<V> {\n\t/**\n\t * The length of the range.\n\t */\n\treadonly length: number;\n\n\t/**\n\t * The value associated with this range.\n\t */\n\treadonly value: V;\n}\n\n/**\n * Describes the result of a range query, including the value and length of the matching prefix.\n */\nexport interface RangeQueryResult<V> {\n\t/**\n\t * The value of the first key in the query range.\n\t */\n\treadonly value: V;\n\n\t/**\n\t * The length of the prefix of the query range which has the same value.\n\t * For example, if a RangeMap has the same value for keys 5, 6, and 7,\n\t * a query about the range [5, 10] would give a result with length 3.\n\t */\n\treadonly length: number;\n}\n\nexport interface RangeQueryResultFragment<V> extends RangeQueryResult<V> {\n\t/**\n\t * The offset from the query key to the key this result is associated with.\n\t * This is useful in the case where a query returns multiple `RangeQueryResults`\n\t * addressing the key range.\n\t */\n\treadonly offset: number;\n}\n\nexport interface RangeMapEntry<K, V> {\n\treadonly start: K;\n\treadonly value: V;\n\treadonly length: number;\n}\n\nexport function newIntegerRangeMap<V, K extends number = number>(): RangeMap<K, V> {\n\treturn new RangeMap(offsetInteger, subtractIntegers);\n}\n\nfunction offsetInteger<K extends number>(key: K, offset: number): K {\n\treturn (key + offset) as K;\n}\n\nfunction subtractIntegers<K extends number>(a: K, b: K): number {\n\treturn a - b;\n}\n\nfunction defaultValueOffsetFn<T>(value: T, offset: number): T {\n\treturn value;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/tree",
3
- "version": "2.103.0",
3
+ "version": "2.110.0",
4
4
  "description": "Distributed tree",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -101,40 +101,41 @@
101
101
  "temp-directory": "nyc/.nyc_output"
102
102
  },
103
103
  "dependencies": {
104
- "@fluid-internal/client-utils": "~2.103.0",
105
- "@fluidframework/container-runtime": "~2.103.0",
106
- "@fluidframework/core-interfaces": "~2.103.0",
107
- "@fluidframework/core-utils": "~2.103.0",
108
- "@fluidframework/datastore-definitions": "~2.103.0",
109
- "@fluidframework/driver-definitions": "~2.103.0",
110
- "@fluidframework/id-compressor": "~2.103.0",
111
- "@fluidframework/runtime-definitions": "~2.103.0",
112
- "@fluidframework/runtime-utils": "~2.103.0",
113
- "@fluidframework/shared-object-base": "~2.103.0",
114
- "@fluidframework/telemetry-utils": "~2.103.0",
115
- "@fluidframework/type-factory": "~2.103.0",
104
+ "@fluid-internal/client-utils": "~2.110.0",
105
+ "@fluidframework/container-runtime": "~2.110.0",
106
+ "@fluidframework/core-interfaces": "~2.110.0",
107
+ "@fluidframework/core-utils": "~2.110.0",
108
+ "@fluidframework/datastore-definitions": "~2.110.0",
109
+ "@fluidframework/driver-definitions": "~2.110.0",
110
+ "@fluidframework/id-compressor": "~2.110.0",
111
+ "@fluidframework/runtime-definitions": "~2.110.0",
112
+ "@fluidframework/runtime-utils": "~2.110.0",
113
+ "@fluidframework/shared-object-base": "~2.110.0",
114
+ "@fluidframework/telemetry-utils": "~2.110.0",
115
+ "@fluidframework/type-factory": "~2.110.0",
116
116
  "@sinclair/typebox": "^0.34.13",
117
117
  "@tylerbu/sorted-btree-es6": "^2.1.1",
118
118
  "semver-ts": "^1.0.3",
119
+ "tslib": "^2.8.1",
119
120
  "uuid": "^11.1.0"
120
121
  },
121
122
  "devDependencies": {
122
123
  "@arethetypeswrong/cli": "^0.18.2",
123
124
  "@biomejs/biome": "~2.4.5",
124
- "@fluid-internal/mocha-test-setup": "~2.103.0",
125
- "@fluid-private/stochastic-test-utils": "~2.103.0",
126
- "@fluid-private/test-dds-utils": "~2.103.0",
127
- "@fluid-private/test-drivers": "~2.103.0",
125
+ "@fluid-internal/mocha-test-setup": "~2.110.0",
126
+ "@fluid-private/stochastic-test-utils": "~2.110.0",
127
+ "@fluid-private/test-dds-utils": "~2.110.0",
128
+ "@fluid-private/test-drivers": "~2.110.0",
128
129
  "@fluid-tools/benchmark": "^0.59.0",
129
130
  "@fluid-tools/build-cli": "^0.65.0",
130
131
  "@fluidframework/build-common": "^2.0.3",
131
132
  "@fluidframework/build-tools": "^0.65.0",
132
- "@fluidframework/container-definitions": "~2.103.0",
133
- "@fluidframework/container-loader": "~2.103.0",
134
- "@fluidframework/eslint-config-fluid": "^9.0.0",
135
- "@fluidframework/test-runtime-utils": "~2.103.0",
136
- "@fluidframework/test-utils": "~2.103.0",
137
- "@fluidframework/tree-previous": "npm:@fluidframework/tree@2.101.0",
133
+ "@fluidframework/container-definitions": "~2.110.0",
134
+ "@fluidframework/container-loader": "~2.110.0",
135
+ "@fluidframework/eslint-config-fluid": "^13.0.0",
136
+ "@fluidframework/test-runtime-utils": "~2.110.0",
137
+ "@fluidframework/test-utils": "~2.110.0",
138
+ "@fluidframework/tree-previous": "npm:@fluidframework/tree@2.103.0",
138
139
  "@microsoft/api-extractor": "7.58.1",
139
140
  "@types/diff": "^3.5.1",
140
141
  "@types/easy-table": "^0.0.32",
@@ -782,6 +782,14 @@ export class ModularChangeFamily
782
782
 
783
783
  const crossFieldKeys = this.makeCrossFieldKeyTable(invertedFields, invertedNodes);
784
784
 
785
+ const constraintState = newConstraintState(0);
786
+ this.updateConstraintsForFields(
787
+ invertedFields,
788
+ NodeAttachState.Attached,
789
+ constraintState,
790
+ invertedNodes,
791
+ );
792
+
785
793
  return makeModularChangeset({
786
794
  fieldChanges: invertedFields,
787
795
  nodeChanges: invertedNodes,
@@ -790,8 +798,7 @@ export class ModularChangeFamily
790
798
  crossFieldKeys,
791
799
  maxId: genId.getMaxId(),
792
800
  revisions: revInfos,
793
- constraintViolationCount: change.change.constraintViolationCountOnRevert,
794
- constraintViolationCountOnRevert: change.change.constraintViolationCount,
801
+ constraintViolationCount: constraintState.violationCount,
795
802
  noChangeConstraint,
796
803
  noChangeConstraintOnRevert,
797
804
  destroys,
@@ -939,9 +946,6 @@ export class ModularChangeFamily
939
946
  );
940
947
 
941
948
  const constraintState = newConstraintState(change.constraintViolationCount ?? 0);
942
- const revertConstraintState = newConstraintState(
943
- change.constraintViolationCountOnRevert ?? 0,
944
- );
945
949
 
946
950
  let noChangeConstraint = change.noChangeConstraint;
947
951
  if (
@@ -956,9 +960,7 @@ export class ModularChangeFamily
956
960
  this.updateConstraintsForFields(
957
961
  rebasedFields,
958
962
  NodeAttachState.Attached,
959
- NodeAttachState.Attached,
960
963
  constraintState,
961
- revertConstraintState,
962
964
  rebasedNodes,
963
965
  );
964
966
 
@@ -971,7 +973,6 @@ export class ModularChangeFamily
971
973
  maxId: idState.maxId,
972
974
  revisions: change.revisions,
973
975
  constraintViolationCount: constraintState.violationCount,
974
- constraintViolationCountOnRevert: revertConstraintState.violationCount,
975
976
  noChangeConstraint,
976
977
  noChangeConstraintOnRevert: change.noChangeConstraintOnRevert,
977
978
  builds: change.builds,
@@ -1410,32 +1411,21 @@ export class ModularChangeFamily
1410
1411
  private updateConstraintsForFields(
1411
1412
  fields: FieldChangeMap,
1412
1413
  parentInputAttachState: NodeAttachState,
1413
- parentOutputAttachState: NodeAttachState,
1414
1414
  constraintState: ConstraintState,
1415
- revertConstraintState: ConstraintState,
1416
1415
  nodes: ChangeAtomIdBTree<NodeChangeset>,
1417
1416
  ): void {
1418
1417
  for (const field of fields.values()) {
1419
1418
  const handler = getChangeHandler(this.fieldKinds, field.fieldKind);
1420
- for (const [nodeId, inputIndex, outputIndex] of handler.getNestedChanges(field.change)) {
1419
+ for (const [nodeId, inputIndex, _outputIndex] of handler.getNestedChanges(
1420
+ field.change,
1421
+ )) {
1421
1422
  const isInputDetached = inputIndex === undefined;
1422
1423
  const inputAttachState =
1423
1424
  parentInputAttachState === NodeAttachState.Detached || isInputDetached
1424
1425
  ? NodeAttachState.Detached
1425
1426
  : NodeAttachState.Attached;
1426
- const isOutputDetached = outputIndex === undefined;
1427
- const outputAttachState =
1428
- parentOutputAttachState === NodeAttachState.Detached || isOutputDetached
1429
- ? NodeAttachState.Detached
1430
- : NodeAttachState.Attached;
1431
- this.updateConstraintsForNode(
1432
- nodeId,
1433
- inputAttachState,
1434
- outputAttachState,
1435
- nodes,
1436
- constraintState,
1437
- revertConstraintState,
1438
- );
1427
+
1428
+ this.updateConstraintsForNode(nodeId, inputAttachState, nodes, constraintState);
1439
1429
  }
1440
1430
  }
1441
1431
  }
@@ -1443,10 +1433,8 @@ export class ModularChangeFamily
1443
1433
  private updateConstraintsForNode(
1444
1434
  nodeId: NodeId,
1445
1435
  inputAttachState: NodeAttachState,
1446
- outputAttachState: NodeAttachState,
1447
1436
  nodes: ChangeAtomIdBTree<NodeChangeset>,
1448
1437
  constraintState: ConstraintState,
1449
- revertConstraintState: ConstraintState,
1450
1438
  ): void {
1451
1439
  const node =
1452
1440
  nodes.get([nodeId.revision, nodeId.localId]) ?? fail(0xb24 /* Unknown node ID */);
@@ -1460,24 +1448,12 @@ export class ModularChangeFamily
1460
1448
  constraintState.violationCount += isNowViolated ? 1 : -1;
1461
1449
  }
1462
1450
  }
1463
- if (node.nodeExistsConstraintOnRevert !== undefined) {
1464
- const isNowViolated = outputAttachState === NodeAttachState.Detached;
1465
- if (node.nodeExistsConstraintOnRevert.violated !== isNowViolated) {
1466
- node.nodeExistsConstraintOnRevert = {
1467
- ...node.nodeExistsConstraintOnRevert,
1468
- violated: isNowViolated,
1469
- };
1470
- revertConstraintState.violationCount += isNowViolated ? 1 : -1;
1471
- }
1472
- }
1473
1451
 
1474
1452
  if (node.fieldChanges !== undefined) {
1475
1453
  this.updateConstraintsForFields(
1476
1454
  node.fieldChanges,
1477
1455
  inputAttachState,
1478
- outputAttachState,
1479
1456
  constraintState,
1480
- revertConstraintState,
1481
1457
  nodes,
1482
1458
  );
1483
1459
  }
@@ -2003,7 +1979,6 @@ export function updateRefreshers(
2003
1979
  maxId,
2004
1980
  revisions,
2005
1981
  constraintViolationCount,
2006
- constraintViolationCountOnRevert,
2007
1982
  builds,
2008
1983
  destroys,
2009
1984
  } = change;
@@ -2017,7 +1992,6 @@ export function updateRefreshers(
2017
1992
  maxId: maxId as number,
2018
1993
  revisions,
2019
1994
  constraintViolationCount,
2020
- constraintViolationCountOnRevert,
2021
1995
  builds,
2022
1996
  destroys,
2023
1997
  refreshers,
@@ -2632,7 +2606,6 @@ function makeModularChangeset(props?: {
2632
2606
  maxId: number;
2633
2607
  revisions?: readonly RevisionInfo[];
2634
2608
  constraintViolationCount?: number;
2635
- constraintViolationCountOnRevert?: number;
2636
2609
  noChangeConstraint?: NoChangeConstraint;
2637
2610
  noChangeConstraintOnRevert?: NoChangeConstraint;
2638
2611
  builds?: ChangeAtomIdBTree<TreeChunk>;
@@ -2657,12 +2630,6 @@ function makeModularChangeset(props?: {
2657
2630
  if (p.constraintViolationCount !== undefined && p.constraintViolationCount > 0) {
2658
2631
  changeset.constraintViolationCount = p.constraintViolationCount;
2659
2632
  }
2660
- if (
2661
- p.constraintViolationCountOnRevert !== undefined &&
2662
- p.constraintViolationCountOnRevert > 0
2663
- ) {
2664
- changeset.constraintViolationCountOnRevert = p.constraintViolationCountOnRevert;
2665
- }
2666
2633
  if (p.noChangeConstraint !== undefined) {
2667
2634
  changeset.noChangeConstraint = p.noChangeConstraint;
2668
2635
  }
@@ -64,11 +64,6 @@ export interface ModularChangeset extends Readonly<HasFieldChanges> {
64
64
  readonly noChangeConstraint?: NoChangeConstraint;
65
65
  /** Constraint that the document must be in the same state before the revert of this change is applied as it was after this change was applied */
66
66
  readonly noChangeConstraintOnRevert?: NoChangeConstraint;
67
- /**
68
- * The number of constraint violations that apply to the revert of the changeset. If this count is greater than 0, it will
69
- * prevent the changeset from being reverted or undone.
70
- */
71
- readonly constraintViolationCountOnRevert?: number;
72
67
  readonly builds?: ChangeAtomIdBTree<TreeChunk>;
73
68
  readonly destroys?: ChangeAtomIdBTree<number>;
74
69
  readonly refreshers?: ChangeAtomIdBTree<TreeChunk>;
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/tree";
9
- export const pkgVersion = "2.103.0";
9
+ export const pkgVersion = "2.110.0";
@@ -529,5 +529,9 @@ export class SchematizingSimpleTreeView<
529
529
  this.checkout.rebaseOnto(context);
530
530
  }
531
531
 
532
+ public isMissingEditsFrom(context: TreeBranchAlpha): boolean {
533
+ return this.checkout.isMissingEditsFrom(context);
534
+ }
535
+
532
536
  // #endregion Branching
533
537
  }