@fluidframework/tree 2.116.0-416006 → 2.116.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 (327) hide show
  1. package/CHANGELOG.md +84 -0
  2. package/README.md +5 -3
  3. package/api-report/tree.alpha.api.md +4 -2
  4. package/api-report/tree.beta.api.md +1 -1
  5. package/api-report/tree.legacy.beta.api.md +1 -1
  6. package/dist/codec/codec.d.ts +6 -6
  7. package/dist/codec/codec.d.ts.map +1 -1
  8. package/dist/codec/codec.js +3 -3
  9. package/dist/codec/codec.js.map +1 -1
  10. package/dist/codec/versioned/codec.d.ts +3 -3
  11. package/dist/codec/versioned/codec.d.ts.map +1 -1
  12. package/dist/codec/versioned/codec.js.map +1 -1
  13. package/dist/core/forest/editableForest.d.ts +2 -0
  14. package/dist/core/forest/editableForest.d.ts.map +1 -1
  15. package/dist/core/forest/editableForest.js.map +1 -1
  16. package/dist/core/index.d.ts +1 -1
  17. package/dist/core/index.d.ts.map +1 -1
  18. package/dist/core/index.js +2 -2
  19. package/dist/core/index.js.map +1 -1
  20. package/dist/core/tree/index.d.ts +1 -1
  21. package/dist/core/tree/index.d.ts.map +1 -1
  22. package/dist/core/tree/index.js +2 -2
  23. package/dist/core/tree/index.js.map +1 -1
  24. package/dist/core/tree/visitorUtils.d.ts +24 -3
  25. package/dist/core/tree/visitorUtils.d.ts.map +1 -1
  26. package/dist/core/tree/visitorUtils.js +24 -6
  27. package/dist/core/tree/visitorUtils.js.map +1 -1
  28. package/dist/feature-libraries/chunked-forest/chunkedForest.d.ts +30 -6
  29. package/dist/feature-libraries/chunked-forest/chunkedForest.d.ts.map +1 -1
  30. package/dist/feature-libraries/chunked-forest/chunkedForest.js +146 -54
  31. package/dist/feature-libraries/chunked-forest/chunkedForest.js.map +1 -1
  32. package/dist/feature-libraries/comparison-forest/comparisonForest.d.ts +2 -1
  33. package/dist/feature-libraries/comparison-forest/comparisonForest.d.ts.map +1 -1
  34. package/dist/feature-libraries/comparison-forest/comparisonForest.js +87 -70
  35. package/dist/feature-libraries/comparison-forest/comparisonForest.js.map +1 -1
  36. package/dist/feature-libraries/detachedFieldIndexSummarizer.js.map +1 -1
  37. package/dist/feature-libraries/forest-summary/forestSummarizer.d.ts +5 -0
  38. package/dist/feature-libraries/forest-summary/forestSummarizer.d.ts.map +1 -1
  39. package/dist/feature-libraries/forest-summary/forestSummarizer.js +127 -107
  40. package/dist/feature-libraries/forest-summary/forestSummarizer.js.map +1 -1
  41. package/dist/feature-libraries/forest-summary/summaryTypes.d.ts +2 -2
  42. package/dist/feature-libraries/forest-summary/summaryTypes.d.ts.map +1 -1
  43. package/dist/feature-libraries/forest-summary/summaryTypes.js.map +1 -1
  44. package/dist/feature-libraries/indexing/anchorTreeIndex.js +1 -1
  45. package/dist/feature-libraries/indexing/anchorTreeIndex.js.map +1 -1
  46. package/dist/feature-libraries/modular-schema/invert.js +1 -1
  47. package/dist/feature-libraries/modular-schema/invert.js.map +1 -1
  48. package/dist/feature-libraries/modular-schema/modularChangeFamily.d.ts.map +1 -1
  49. package/dist/feature-libraries/modular-schema/modularChangeFamily.js +2 -11
  50. package/dist/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
  51. package/dist/feature-libraries/modular-schema/modularChangeUtils.d.ts +11 -16
  52. package/dist/feature-libraries/modular-schema/modularChangeUtils.d.ts.map +1 -1
  53. package/dist/feature-libraries/modular-schema/modularChangeUtils.js +10 -3
  54. package/dist/feature-libraries/modular-schema/modularChangeUtils.js.map +1 -1
  55. package/dist/feature-libraries/object-forest/objectForest.d.ts.map +1 -1
  56. package/dist/feature-libraries/object-forest/objectForest.js +34 -13
  57. package/dist/feature-libraries/object-forest/objectForest.js.map +1 -1
  58. package/dist/feature-libraries/schema-index/schemaSummarizer.d.ts +2 -2
  59. package/dist/feature-libraries/schema-index/schemaSummarizer.d.ts.map +1 -1
  60. package/dist/feature-libraries/schema-index/schemaSummarizer.js.map +1 -1
  61. package/dist/feature-libraries/sequence-field/rebase.js +1 -1
  62. package/dist/feature-libraries/sequence-field/rebase.js.map +1 -1
  63. package/dist/feature-libraries/sequence-field/utils.js +1 -1
  64. package/dist/feature-libraries/sequence-field/utils.js.map +1 -1
  65. package/dist/packageVersion.d.ts +1 -1
  66. package/dist/packageVersion.d.ts.map +1 -1
  67. package/dist/packageVersion.js +1 -1
  68. package/dist/packageVersion.js.map +1 -1
  69. package/dist/shared-tree/independentView.d.ts.map +1 -1
  70. package/dist/shared-tree/independentView.js +2 -4
  71. package/dist/shared-tree/independentView.js.map +1 -1
  72. package/dist/shared-tree/sharedTree.d.ts +30 -5
  73. package/dist/shared-tree/sharedTree.d.ts.map +1 -1
  74. package/dist/shared-tree/sharedTree.js +8 -8
  75. package/dist/shared-tree/sharedTree.js.map +1 -1
  76. package/dist/shared-tree/sharedTreeChangeCodecs.d.ts +2 -2
  77. package/dist/shared-tree/sharedTreeChangeCodecs.d.ts.map +1 -1
  78. package/dist/shared-tree/sharedTreeChangeCodecs.js.map +1 -1
  79. package/dist/shared-tree/sharedTreeChangeEnricher.d.ts +25 -1
  80. package/dist/shared-tree/sharedTreeChangeEnricher.d.ts.map +1 -1
  81. package/dist/shared-tree/sharedTreeChangeEnricher.js +24 -0
  82. package/dist/shared-tree/sharedTreeChangeEnricher.js.map +1 -1
  83. package/dist/shared-tree/treeCheckout.d.ts +21 -10
  84. package/dist/shared-tree/treeCheckout.d.ts.map +1 -1
  85. package/dist/shared-tree/treeCheckout.js +48 -16
  86. package/dist/shared-tree/treeCheckout.js.map +1 -1
  87. package/dist/shared-tree-core/branchCommitEnricher.d.ts +2 -1
  88. package/dist/shared-tree-core/branchCommitEnricher.d.ts.map +1 -1
  89. package/dist/shared-tree-core/branchCommitEnricher.js +3 -2
  90. package/dist/shared-tree-core/branchCommitEnricher.js.map +1 -1
  91. package/dist/shared-tree-core/changeEnricher.d.ts +3 -2
  92. package/dist/shared-tree-core/changeEnricher.d.ts.map +1 -1
  93. package/dist/shared-tree-core/changeEnricher.js.map +1 -1
  94. package/dist/shared-tree-core/defaultResubmitMachine.d.ts +9 -1
  95. package/dist/shared-tree-core/defaultResubmitMachine.d.ts.map +1 -1
  96. package/dist/shared-tree-core/defaultResubmitMachine.js +7 -2
  97. package/dist/shared-tree-core/defaultResubmitMachine.js.map +1 -1
  98. package/dist/shared-tree-core/editManager.d.ts.map +1 -1
  99. package/dist/shared-tree-core/editManager.js +2 -2
  100. package/dist/shared-tree-core/editManager.js.map +1 -1
  101. package/dist/shared-tree-core/editManagerCodecs.d.ts +2 -2
  102. package/dist/shared-tree-core/editManagerCodecs.d.ts.map +1 -1
  103. package/dist/shared-tree-core/editManagerCodecs.js.map +1 -1
  104. package/dist/shared-tree-core/editManagerSummarizer.d.ts +2 -2
  105. package/dist/shared-tree-core/editManagerSummarizer.d.ts.map +1 -1
  106. package/dist/shared-tree-core/editManagerSummarizer.js.map +1 -1
  107. package/dist/shared-tree-core/messageCodecs.d.ts +2 -2
  108. package/dist/shared-tree-core/messageCodecs.d.ts.map +1 -1
  109. package/dist/shared-tree-core/messageCodecs.js.map +1 -1
  110. package/dist/shared-tree-core/sharedTreeCore.d.ts +11 -2
  111. package/dist/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
  112. package/dist/shared-tree-core/sharedTreeCore.js +11 -8
  113. package/dist/shared-tree-core/sharedTreeCore.js.map +1 -1
  114. package/dist/shared-tree-core/summaryTypes.d.ts +2 -2
  115. package/dist/shared-tree-core/summaryTypes.d.ts.map +1 -1
  116. package/dist/shared-tree-core/summaryTypes.js.map +1 -1
  117. package/dist/simple-tree/api/snapshotCompatibilityChecker.d.ts +1 -1
  118. package/dist/simple-tree/api/snapshotCompatibilityChecker.js.map +1 -1
  119. package/dist/simple-tree/api/storedSchema.d.ts +2 -2
  120. package/dist/simple-tree/api/storedSchema.d.ts.map +1 -1
  121. package/dist/simple-tree/api/storedSchema.js.map +1 -1
  122. package/dist/simple-tree/api/treeChangeEvents.d.ts +5 -1
  123. package/dist/simple-tree/api/treeChangeEvents.d.ts.map +1 -1
  124. package/dist/simple-tree/api/treeChangeEvents.js.map +1 -1
  125. package/dist/simple-tree/node-kinds/array/arrayNode.d.ts.map +1 -1
  126. package/dist/simple-tree/node-kinds/array/arrayNode.js +10 -0
  127. package/dist/simple-tree/node-kinds/array/arrayNode.js.map +1 -1
  128. package/dist/simple-tree/node-kinds/map/mapNode.d.ts.map +1 -1
  129. package/dist/simple-tree/node-kinds/map/mapNode.js +19 -2
  130. package/dist/simple-tree/node-kinds/map/mapNode.js.map +1 -1
  131. package/dist/tableSchema.d.ts +1 -1
  132. package/dist/tableSchema.js +1 -1
  133. package/dist/tableSchema.js.map +1 -1
  134. package/dist/treeFactory.d.ts.map +1 -1
  135. package/dist/treeFactory.js +1 -1
  136. package/dist/treeFactory.js.map +1 -1
  137. package/dist/util/breakable.d.ts +14 -2
  138. package/dist/util/breakable.d.ts.map +1 -1
  139. package/dist/util/breakable.js +9 -1
  140. package/dist/util/breakable.js.map +1 -1
  141. package/dist/util/compressedIds.d.ts +2 -2
  142. package/dist/util/compressedIds.d.ts.map +1 -1
  143. package/dist/util/compressedIds.js +1 -6
  144. package/dist/util/compressedIds.js.map +1 -1
  145. package/lib/codec/codec.d.ts +6 -6
  146. package/lib/codec/codec.d.ts.map +1 -1
  147. package/lib/codec/codec.js +3 -3
  148. package/lib/codec/codec.js.map +1 -1
  149. package/lib/codec/versioned/codec.d.ts +3 -3
  150. package/lib/codec/versioned/codec.d.ts.map +1 -1
  151. package/lib/codec/versioned/codec.js.map +1 -1
  152. package/lib/core/forest/editableForest.d.ts +2 -0
  153. package/lib/core/forest/editableForest.d.ts.map +1 -1
  154. package/lib/core/forest/editableForest.js.map +1 -1
  155. package/lib/core/index.d.ts +1 -1
  156. package/lib/core/index.d.ts.map +1 -1
  157. package/lib/core/index.js +1 -1
  158. package/lib/core/index.js.map +1 -1
  159. package/lib/core/tree/index.d.ts +1 -1
  160. package/lib/core/tree/index.d.ts.map +1 -1
  161. package/lib/core/tree/index.js +1 -1
  162. package/lib/core/tree/index.js.map +1 -1
  163. package/lib/core/tree/visitorUtils.d.ts +24 -3
  164. package/lib/core/tree/visitorUtils.d.ts.map +1 -1
  165. package/lib/core/tree/visitorUtils.js +22 -4
  166. package/lib/core/tree/visitorUtils.js.map +1 -1
  167. package/lib/feature-libraries/chunked-forest/chunkedForest.d.ts +30 -6
  168. package/lib/feature-libraries/chunked-forest/chunkedForest.d.ts.map +1 -1
  169. package/lib/feature-libraries/chunked-forest/chunkedForest.js +146 -56
  170. package/lib/feature-libraries/chunked-forest/chunkedForest.js.map +1 -1
  171. package/lib/feature-libraries/comparison-forest/comparisonForest.d.ts +2 -1
  172. package/lib/feature-libraries/comparison-forest/comparisonForest.d.ts.map +1 -1
  173. package/lib/feature-libraries/comparison-forest/comparisonForest.js +88 -70
  174. package/lib/feature-libraries/comparison-forest/comparisonForest.js.map +1 -1
  175. package/lib/feature-libraries/detachedFieldIndexSummarizer.js.map +1 -1
  176. package/lib/feature-libraries/forest-summary/forestSummarizer.d.ts +5 -0
  177. package/lib/feature-libraries/forest-summary/forestSummarizer.d.ts.map +1 -1
  178. package/lib/feature-libraries/forest-summary/forestSummarizer.js +129 -108
  179. package/lib/feature-libraries/forest-summary/forestSummarizer.js.map +1 -1
  180. package/lib/feature-libraries/forest-summary/summaryTypes.d.ts +2 -2
  181. package/lib/feature-libraries/forest-summary/summaryTypes.d.ts.map +1 -1
  182. package/lib/feature-libraries/forest-summary/summaryTypes.js.map +1 -1
  183. package/lib/feature-libraries/indexing/anchorTreeIndex.js +1 -1
  184. package/lib/feature-libraries/indexing/anchorTreeIndex.js.map +1 -1
  185. package/lib/feature-libraries/modular-schema/invert.js +2 -2
  186. package/lib/feature-libraries/modular-schema/invert.js.map +1 -1
  187. package/lib/feature-libraries/modular-schema/modularChangeFamily.d.ts.map +1 -1
  188. package/lib/feature-libraries/modular-schema/modularChangeFamily.js +2 -11
  189. package/lib/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
  190. package/lib/feature-libraries/modular-schema/modularChangeUtils.d.ts +11 -16
  191. package/lib/feature-libraries/modular-schema/modularChangeUtils.d.ts.map +1 -1
  192. package/lib/feature-libraries/modular-schema/modularChangeUtils.js +10 -3
  193. package/lib/feature-libraries/modular-schema/modularChangeUtils.js.map +1 -1
  194. package/lib/feature-libraries/object-forest/objectForest.d.ts.map +1 -1
  195. package/lib/feature-libraries/object-forest/objectForest.js +35 -14
  196. package/lib/feature-libraries/object-forest/objectForest.js.map +1 -1
  197. package/lib/feature-libraries/schema-index/schemaSummarizer.d.ts +2 -2
  198. package/lib/feature-libraries/schema-index/schemaSummarizer.d.ts.map +1 -1
  199. package/lib/feature-libraries/schema-index/schemaSummarizer.js.map +1 -1
  200. package/lib/feature-libraries/sequence-field/rebase.js +2 -2
  201. package/lib/feature-libraries/sequence-field/rebase.js.map +1 -1
  202. package/lib/feature-libraries/sequence-field/utils.js +1 -1
  203. package/lib/feature-libraries/sequence-field/utils.js.map +1 -1
  204. package/lib/packageVersion.d.ts +1 -1
  205. package/lib/packageVersion.d.ts.map +1 -1
  206. package/lib/packageVersion.js +1 -1
  207. package/lib/packageVersion.js.map +1 -1
  208. package/lib/shared-tree/independentView.d.ts.map +1 -1
  209. package/lib/shared-tree/independentView.js +3 -5
  210. package/lib/shared-tree/independentView.js.map +1 -1
  211. package/lib/shared-tree/sharedTree.d.ts +30 -5
  212. package/lib/shared-tree/sharedTree.d.ts.map +1 -1
  213. package/lib/shared-tree/sharedTree.js +8 -8
  214. package/lib/shared-tree/sharedTree.js.map +1 -1
  215. package/lib/shared-tree/sharedTreeChangeCodecs.d.ts +2 -2
  216. package/lib/shared-tree/sharedTreeChangeCodecs.d.ts.map +1 -1
  217. package/lib/shared-tree/sharedTreeChangeCodecs.js.map +1 -1
  218. package/lib/shared-tree/sharedTreeChangeEnricher.d.ts +25 -1
  219. package/lib/shared-tree/sharedTreeChangeEnricher.d.ts.map +1 -1
  220. package/lib/shared-tree/sharedTreeChangeEnricher.js +24 -0
  221. package/lib/shared-tree/sharedTreeChangeEnricher.js.map +1 -1
  222. package/lib/shared-tree/treeCheckout.d.ts +21 -10
  223. package/lib/shared-tree/treeCheckout.d.ts.map +1 -1
  224. package/lib/shared-tree/treeCheckout.js +48 -16
  225. package/lib/shared-tree/treeCheckout.js.map +1 -1
  226. package/lib/shared-tree-core/branchCommitEnricher.d.ts +2 -1
  227. package/lib/shared-tree-core/branchCommitEnricher.d.ts.map +1 -1
  228. package/lib/shared-tree-core/branchCommitEnricher.js +3 -2
  229. package/lib/shared-tree-core/branchCommitEnricher.js.map +1 -1
  230. package/lib/shared-tree-core/changeEnricher.d.ts +3 -2
  231. package/lib/shared-tree-core/changeEnricher.d.ts.map +1 -1
  232. package/lib/shared-tree-core/changeEnricher.js.map +1 -1
  233. package/lib/shared-tree-core/defaultResubmitMachine.d.ts +9 -1
  234. package/lib/shared-tree-core/defaultResubmitMachine.d.ts.map +1 -1
  235. package/lib/shared-tree-core/defaultResubmitMachine.js +7 -2
  236. package/lib/shared-tree-core/defaultResubmitMachine.js.map +1 -1
  237. package/lib/shared-tree-core/editManager.d.ts.map +1 -1
  238. package/lib/shared-tree-core/editManager.js +2 -2
  239. package/lib/shared-tree-core/editManager.js.map +1 -1
  240. package/lib/shared-tree-core/editManagerCodecs.d.ts +2 -2
  241. package/lib/shared-tree-core/editManagerCodecs.d.ts.map +1 -1
  242. package/lib/shared-tree-core/editManagerCodecs.js.map +1 -1
  243. package/lib/shared-tree-core/editManagerSummarizer.d.ts +2 -2
  244. package/lib/shared-tree-core/editManagerSummarizer.d.ts.map +1 -1
  245. package/lib/shared-tree-core/editManagerSummarizer.js.map +1 -1
  246. package/lib/shared-tree-core/messageCodecs.d.ts +2 -2
  247. package/lib/shared-tree-core/messageCodecs.d.ts.map +1 -1
  248. package/lib/shared-tree-core/messageCodecs.js.map +1 -1
  249. package/lib/shared-tree-core/sharedTreeCore.d.ts +11 -2
  250. package/lib/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
  251. package/lib/shared-tree-core/sharedTreeCore.js +11 -8
  252. package/lib/shared-tree-core/sharedTreeCore.js.map +1 -1
  253. package/lib/shared-tree-core/summaryTypes.d.ts +2 -2
  254. package/lib/shared-tree-core/summaryTypes.d.ts.map +1 -1
  255. package/lib/shared-tree-core/summaryTypes.js.map +1 -1
  256. package/lib/simple-tree/api/snapshotCompatibilityChecker.d.ts +1 -1
  257. package/lib/simple-tree/api/snapshotCompatibilityChecker.js.map +1 -1
  258. package/lib/simple-tree/api/storedSchema.d.ts +2 -2
  259. package/lib/simple-tree/api/storedSchema.d.ts.map +1 -1
  260. package/lib/simple-tree/api/storedSchema.js.map +1 -1
  261. package/lib/simple-tree/api/treeChangeEvents.d.ts +5 -1
  262. package/lib/simple-tree/api/treeChangeEvents.d.ts.map +1 -1
  263. package/lib/simple-tree/api/treeChangeEvents.js.map +1 -1
  264. package/lib/simple-tree/node-kinds/array/arrayNode.d.ts.map +1 -1
  265. package/lib/simple-tree/node-kinds/array/arrayNode.js +10 -0
  266. package/lib/simple-tree/node-kinds/array/arrayNode.js.map +1 -1
  267. package/lib/simple-tree/node-kinds/map/mapNode.d.ts.map +1 -1
  268. package/lib/simple-tree/node-kinds/map/mapNode.js +19 -2
  269. package/lib/simple-tree/node-kinds/map/mapNode.js.map +1 -1
  270. package/lib/tableSchema.d.ts +1 -1
  271. package/lib/tableSchema.js +1 -1
  272. package/lib/tableSchema.js.map +1 -1
  273. package/lib/treeFactory.d.ts.map +1 -1
  274. package/lib/treeFactory.js +1 -1
  275. package/lib/treeFactory.js.map +1 -1
  276. package/lib/util/breakable.d.ts +14 -2
  277. package/lib/util/breakable.d.ts.map +1 -1
  278. package/lib/util/breakable.js +9 -1
  279. package/lib/util/breakable.js.map +1 -1
  280. package/lib/util/compressedIds.d.ts +2 -2
  281. package/lib/util/compressedIds.d.ts.map +1 -1
  282. package/lib/util/compressedIds.js +1 -6
  283. package/lib/util/compressedIds.js.map +1 -1
  284. package/package.json +27 -27
  285. package/src/codec/codec.ts +7 -7
  286. package/src/codec/versioned/codec.ts +5 -5
  287. package/src/core/forest/editableForest.ts +2 -0
  288. package/src/core/index.ts +1 -1
  289. package/src/core/tree/index.ts +1 -1
  290. package/src/core/tree/visitorUtils.ts +37 -12
  291. package/src/feature-libraries/chunked-forest/chunkedForest.ts +214 -59
  292. package/src/feature-libraries/comparison-forest/comparisonForest.ts +6 -1
  293. package/src/feature-libraries/detachedFieldIndexSummarizer.ts +2 -2
  294. package/src/feature-libraries/forest-summary/forestSummarizer.ts +10 -0
  295. package/src/feature-libraries/forest-summary/summaryTypes.ts +2 -2
  296. package/src/feature-libraries/indexing/anchorTreeIndex.ts +1 -1
  297. package/src/feature-libraries/modular-schema/invert.ts +2 -2
  298. package/src/feature-libraries/modular-schema/modularChangeFamily.ts +2 -23
  299. package/src/feature-libraries/modular-schema/modularChangeUtils.ts +12 -21
  300. package/src/feature-libraries/object-forest/objectForest.ts +48 -14
  301. package/src/feature-libraries/schema-index/schemaSummarizer.ts +3 -3
  302. package/src/feature-libraries/sequence-field/rebase.ts +2 -2
  303. package/src/feature-libraries/sequence-field/utils.ts +1 -1
  304. package/src/packageVersion.ts +1 -1
  305. package/src/shared-tree/independentView.ts +5 -12
  306. package/src/shared-tree/sharedTree.ts +41 -10
  307. package/src/shared-tree/sharedTreeChangeCodecs.ts +2 -2
  308. package/src/shared-tree/sharedTreeChangeEnricher.ts +25 -1
  309. package/src/shared-tree/treeCheckout.ts +45 -16
  310. package/src/shared-tree-core/branchCommitEnricher.ts +6 -2
  311. package/src/shared-tree-core/changeEnricher.ts +7 -2
  312. package/src/shared-tree-core/defaultResubmitMachine.ts +5 -0
  313. package/src/shared-tree-core/editManager.ts +2 -4
  314. package/src/shared-tree-core/editManagerCodecs.ts +2 -2
  315. package/src/shared-tree-core/editManagerSummarizer.ts +3 -3
  316. package/src/shared-tree-core/messageCodecs.ts +2 -2
  317. package/src/shared-tree-core/sharedTreeCore.ts +29 -11
  318. package/src/shared-tree-core/summaryTypes.ts +2 -2
  319. package/src/simple-tree/api/snapshotCompatibilityChecker.ts +1 -1
  320. package/src/simple-tree/api/storedSchema.ts +2 -2
  321. package/src/simple-tree/api/treeChangeEvents.ts +5 -1
  322. package/src/simple-tree/node-kinds/array/arrayNode.ts +15 -0
  323. package/src/simple-tree/node-kinds/map/mapNode.ts +23 -2
  324. package/src/tableSchema.ts +1 -1
  325. package/src/treeFactory.ts +0 -1
  326. package/src/util/breakable.ts +9 -1
  327. package/src/util/compressedIds.ts +7 -13
@@ -3,7 +3,7 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { type IdAllocator, idAllocatorFromMaxId } from "../../util/index.js";
6
+ import { type Breakable, type IdAllocator, idAllocatorFromMaxId } from "../../util/index.js";
7
7
  import type { RevisionTag } from "../rebase/index.js";
8
8
  import type { FieldKey } from "../schema-stored/index.js";
9
9
 
@@ -29,28 +29,53 @@ export function applyDelta(
29
29
  visitor.free();
30
30
  }
31
31
 
32
- export function announceDelta(
33
- delta: Root,
34
- latestRevision: RevisionTag | undefined,
35
- deltaProcessor: { acquireVisitor: () => DeltaVisitor & AnnouncedVisitor },
36
- detachedFieldIndex: DetachedFieldIndex,
37
- ): void {
38
- const visitor = deltaProcessor.acquireVisitor();
39
- visitDelta(delta, combineVisitors([visitor]), detachedFieldIndex, latestRevision);
40
- visitor.free();
41
- }
42
-
43
32
  export interface CombinedVisitor extends DeltaVisitor {
44
33
  readonly type: "Combined";
45
34
 
46
35
  readonly visitors: readonly CombinableVisitor[];
47
36
  }
48
37
 
38
+ /**
39
+ * A visitor accepted by {@link combineVisitors}.
40
+ *
41
+ * @remarks
42
+ * Plain {@link DeltaVisitor}s are intersected with `{ readonly type?: never }` so this forms a
43
+ * discriminated union with {@link AnnouncedVisitor} and {@link CombinedVisitor}. The optional
44
+ * `never` property permits visitors without a `type`, while preventing a visitor with an unknown
45
+ * or widened `type` from being treated as plain and losing its specialized composition behavior.
46
+ */
49
47
  export type CombinableVisitor =
50
48
  | (DeltaVisitor & { type?: never })
51
49
  | AnnouncedVisitor
52
50
  | CombinedVisitor;
53
51
 
52
+ /**
53
+ * Wraps a visitor so any error breaks the supplied scope and all subsequent calls fail.
54
+ *
55
+ * @remarks
56
+ * The `{ readonly type?: never }` intersection restricts this helper to plain visitors. Wrapping
57
+ * an {@link AnnouncedVisitor} or {@link CombinedVisitor} as a plain visitor would hide its `type`
58
+ * discriminator and prevent {@link combineVisitors} from preserving announced-event ordering or
59
+ * flattening nested combined visitors.
60
+ */
61
+ export function makeBreakingVisitor(
62
+ visitor: DeltaVisitor & { readonly type?: never },
63
+ breaker: Breakable,
64
+ ): DeltaVisitor & { readonly type?: never } {
65
+ return {
66
+ free: () => breaker.run(() => visitor.free()),
67
+ create: (...args) => breaker.run(() => visitor.create(...args)),
68
+ destroy: (...args) => breaker.run(() => visitor.destroy(...args)),
69
+ attach: (...args) => breaker.run(() => visitor.attach(...args)),
70
+ detach: (...args) => breaker.run(() => visitor.detach(...args)),
71
+ enterNode: (...args) => breaker.run(() => visitor.enterNode(...args)),
72
+ exitNode: (...args) => breaker.run(() => visitor.exitNode(...args)),
73
+ enterField: (...args) => breaker.run(() => visitor.enterField(...args)),
74
+ exitField: (...args) => breaker.run(() => visitor.exitField(...args)),
75
+ fieldMarks: (...args) => breaker.run(() => visitor.fieldMarks?.(...args)),
76
+ };
77
+ }
78
+
54
79
  /**
55
80
  * Combines multiple visitors into a single visitor.
56
81
  * @param visitors - The returned visitor invokes the corresponding events for all these visitors, in order.
@@ -5,7 +5,7 @@
5
5
 
6
6
  import { createEmitter } from "@fluid-internal/client-utils";
7
7
  import type { Listenable } from "@fluidframework/core-interfaces";
8
- import { assert, oob, fail } from "@fluidframework/core-utils/internal";
8
+ import { assert, oob, fail, debugAssert } from "@fluidframework/core-utils/internal";
9
9
  import type { IIdCompressor } from "@fluidframework/id-compressor";
10
10
 
11
11
  import {
@@ -29,6 +29,7 @@ import {
29
29
  aboveRootPlaceholder,
30
30
  combineVisitors,
31
31
  detachedFieldAsKey,
32
+ makeBreakingVisitor,
32
33
  mapCursorField,
33
34
  rootFieldKey,
34
35
  type ChunkedCursor,
@@ -36,11 +37,13 @@ import {
36
37
  type DeltaDetachedNodeId,
37
38
  } from "../../core/index.js";
38
39
  import {
40
+ assertNonNegativeSafeInteger,
39
41
  brand,
40
42
  getLast,
41
43
  getOrAddEmptyToMap,
42
44
  hasSome,
43
- type Breakable,
45
+ Breakable,
46
+ type WithBreakable,
44
47
  } from "../../util/index.js";
45
48
 
46
49
  import { BasicChunk, BasicChunkCursor, type SiblingsOrKey } from "./basicChunk.js";
@@ -57,8 +60,112 @@ function makeRoot(): BasicChunk {
57
60
  return new BasicChunk(aboveRootPlaceholder, new Map());
58
61
  }
59
62
 
63
+ /** Returns the number of top-level nodes represented by a field's chunks. */
64
+ function getFieldLength(field: readonly TreeChunk[]): number {
65
+ return field.reduce((length, chunk) => length + chunk.topLevelLength, 0);
66
+ }
67
+
68
+ /**
69
+ * Locates a top-level node within a field's chunk representation.
70
+ * @param chunks - The chunks representing the field.
71
+ * @param index - The node index within the field.
72
+ * @returns The containing chunk, its array index, and the node's offset within it.
73
+ */
74
+ export function locateNodeInChunks(
75
+ chunks: readonly TreeChunk[],
76
+ index: number,
77
+ ): { chunk: TreeChunk; indexOfChunk: number; indexWithinChunk: number } {
78
+ assertNonNegativeSafeInteger(index);
79
+ // Remaining node offset while scanning chunks; afterward, the offset within the matched chunk.
80
+ let indexWithinChunk = index;
81
+ // Array index of the chunk currently being examined.
82
+ let indexOfChunk = 0;
83
+ while (true) {
84
+ const chunk = chunks[indexOfChunk] ?? oob();
85
+ if (indexWithinChunk < chunk.topLevelLength) {
86
+ return { chunk, indexOfChunk, indexWithinChunk };
87
+ }
88
+ indexWithinChunk -= chunk.topLevelLength;
89
+ indexOfChunk++;
90
+ if (indexOfChunk === chunks.length) {
91
+ fail(0xaf7 /* missing edited node */);
92
+ }
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Ensures the node at index `index` within the field represented by `chunks` is contained in a non-shared {@link BasicChunk}.
98
+ *
99
+ * @param chunks - The chunks representing the field which will be modified to ensure the node at
100
+ * `index` is in a non-shared {@link BasicChunk}.
101
+ * @param index - The node index within the field.
102
+ * @returns The exclusively owned {@link BasicChunk} containing the node at `index`. This chunk is part of and owned by `chunks`.
103
+ * @remarks
104
+ * This function may modify the `chunks` array to ensure the node at `index` is in a non-shared {@link BasicChunk}.
105
+ * This can include splitting chunks, and cloning.
106
+ */
107
+ export function ensureExclusiveBasicChunk(
108
+ chunks: TreeChunk[],
109
+ index: number,
110
+ compressor: ChunkCompressor,
111
+ ): BasicChunk {
112
+ const { chunk, indexOfChunk, indexWithinChunk } = locateNodeInChunks(chunks, index);
113
+
114
+ // Normalize to a BasicChunk, splitting the chunk if needed.
115
+ let finalIndexOfChunk: number;
116
+ let basicChunk: BasicChunk;
117
+ if (chunk instanceof BasicChunk) {
118
+ basicChunk = chunk;
119
+ finalIndexOfChunk = indexOfChunk;
120
+ } else {
121
+ // TODO:Perf: support in place editing of other chunk formats when possible:
122
+ // 1. Support updating values in uniform chunks.
123
+ // 2. Support traversing sequence chunks.
124
+ //
125
+ // Maybe build path when visitor navigates then lazily sync to chunk tree when editing?
126
+ const newChunks = mapCursorField(chunk.cursor(), (cursor) =>
127
+ basicChunkTree(cursor, compressor),
128
+ );
129
+ // TODO: this could fail for really long chunks being split (due to argument count limits).
130
+ // Current implementations of chunks shouldn't ever be that long, but it could be an issue if they get bigger.
131
+ chunks.splice(indexOfChunk, 1, ...newChunks);
132
+ // We just overwrote the reference to the old chunk in the array, so drop the ref count for it.
133
+ chunk.referenceRemoved();
134
+
135
+ // Sanity check that the chunk indexing is as expected before updating it.
136
+ debugAssert(
137
+ () =>
138
+ newChunks[indexWithinChunk] === chunks[indexOfChunk + indexWithinChunk] ||
139
+ "bad chunk indexing",
140
+ );
141
+ basicChunk = newChunks[indexWithinChunk] ?? oob();
142
+ finalIndexOfChunk = indexOfChunk + indexWithinChunk;
143
+ }
144
+
145
+ debugAssert(() => chunks[finalIndexOfChunk] === basicChunk || "bad child index");
146
+
147
+ // Ensure the BasicChunk we have is exclusively owned, so we can edit it in place.
148
+ let exclusiveChunk: BasicChunk;
149
+ if (basicChunk.isShared()) {
150
+ exclusiveChunk = chunks[finalIndexOfChunk] = basicChunk.clone();
151
+ basicChunk.referenceRemoved();
152
+ } else {
153
+ exclusiveChunk = basicChunk;
154
+ }
155
+ return exclusiveChunk;
156
+ }
157
+
158
+ /**
159
+ * Layer in the stack of basic chunks from traversing down the tree.
160
+ */
60
161
  interface StackNode {
162
+ /**
163
+ * The parent node.
164
+ */
61
165
  mutableChunk: BasicChunk;
166
+ /**
167
+ * A key under {@link mutableChunk} into which this stack traverses.
168
+ */
62
169
  key: FieldKey;
63
170
  }
64
171
 
@@ -67,7 +174,7 @@ interface StackNode {
67
174
  *
68
175
  * This implementation focuses on performance.
69
176
  */
70
- export class ChunkedForest implements IEditableForest {
177
+ export class ChunkedForest implements IEditableForest, WithBreakable {
71
178
  private activeVisitor?: DeltaVisitor;
72
179
 
73
180
  private readonly deltaVisitors: Set<() => AnnouncedVisitor> = new Set();
@@ -86,18 +193,29 @@ export class ChunkedForest implements IEditableForest {
86
193
  public readonly chunker: IChunker,
87
194
  public readonly anchors: AnchorSet = new AnchorSet(),
88
195
  public readonly idCompressor?: IIdCompressor,
196
+ public readonly breaker: Breakable = new Breakable("ChunkedForest"),
89
197
  ) {}
90
198
 
91
199
  public get isEmpty(): boolean {
200
+ this.breaker.use();
92
201
  return this.roots.fields.size === 0;
93
202
  }
94
203
 
95
- public clone(schema: TreeStoredSchemaSubscription, _breaker?: Breakable): ChunkedForest {
204
+ public clone(schema: TreeStoredSchemaSubscription, breaker?: Breakable): ChunkedForest {
205
+ this.breaker.use();
96
206
  this.roots.referenceAdded();
97
- return new ChunkedForest(this.roots, schema, this.chunker.clone(schema));
207
+ return new ChunkedForest(
208
+ this.roots,
209
+ schema,
210
+ this.chunker.clone(schema),
211
+ undefined,
212
+ this.idCompressor,
213
+ breaker ?? this.breaker,
214
+ );
98
215
  }
99
216
 
100
217
  public chunkField(cursor: ITreeCursorSynchronous): TreeChunk[] {
218
+ this.breaker.use();
101
219
  return chunkField(cursor, { idCompressor: this.idCompressor, policy: this.chunker });
102
220
  }
103
221
 
@@ -114,6 +232,7 @@ export class ChunkedForest implements IEditableForest {
114
232
  }
115
233
 
116
234
  public acquireVisitor(): DeltaVisitor {
235
+ this.breaker.use();
117
236
  assert(
118
237
  this.activeVisitor === undefined,
119
238
  0x76a /* Must release existing visitor before acquiring another */,
@@ -123,11 +242,24 @@ export class ChunkedForest implements IEditableForest {
123
242
  this.roots = this.roots.clone();
124
243
  }
125
244
 
245
+ // The `CombinableVisitor` which can apply deltas to this forest.
246
+ // Annoyingly declaring the type here or in a satisfies clause causes this code not to build,
247
+ // so the type is inferred.
248
+ //
249
+ // This visitor works by shallow copying (where needed) the forest as it's walked down
250
+ // to ensure the location being traversed (and thus possibly edited) is an exclusively owned BasicChunk.
251
+ // Future optimizations may improve this, but currently that is a requirement for the editing code to work.
126
252
  const forestVisitor = {
127
253
  forest: this,
128
- // Current location in the tree, as a non-shared BasicChunk (TODO: support in-place modification of other chunk formats when possible).
129
- // Start above root detached sequences.
254
+ /**
255
+ * Current location in the tree, as a non-shared BasicChunk (TODO: support in-place modification of other chunk formats when possible).
256
+ * Starts above root detached sequences.
257
+ */
130
258
  mutableChunkStack: [] as StackNode[],
259
+ /**
260
+ * When at a node level, this is set to the basic chunk for the current node.
261
+ * When at a field level, undefined, see mutableChunkStack for the field.
262
+ */
131
263
  mutableChunk: this.roots as BasicChunk | undefined,
132
264
  getParent(): StackNode {
133
265
  assert(hasSome(this.mutableChunkStack), 0x532 /* invalid access to root's parent */);
@@ -144,10 +276,23 @@ export class ChunkedForest implements IEditableForest {
144
276
  },
145
277
  destroy(detachedField: FieldKey, count: number): void {
146
278
  this.forest.#events.emit("beforeChange");
279
+ const field = this.forest.roots.fields.get(detachedField);
280
+ assert(field !== undefined, 0xd1d /* Destroyed field must exist */);
281
+ assert(
282
+ getFieldLength(field) === count,
283
+ 0xd1e /* Destroy count must match field length */,
284
+ );
147
285
  this.forest.roots.fields.delete(detachedField);
286
+ for (const chunk of field) {
287
+ chunk.referenceRemoved();
288
+ }
148
289
  },
149
290
  create(content: readonly ITreeCursorSynchronous[], destination: FieldKey): void {
150
291
  this.forest.#events.emit("beforeChange");
292
+ assert(
293
+ !this.forest.roots.fields.has(destination),
294
+ 0xd1f /* Create destination must be a new empty field */,
295
+ );
151
296
  const chunks: TreeChunk[] = content.map((c) =>
152
297
  chunkTree(c, {
153
298
  policy: this.forest.chunker,
@@ -171,18 +316,27 @@ export class ChunkedForest implements IEditableForest {
171
316
  */
172
317
  attachEdit(source: FieldKey, count: number, destination: PlaceIndex): void {
173
318
  this.forest.#events.emit("beforeChange");
174
- const sourceField = this.forest.roots.fields.get(source) ?? [];
175
- this.forest.roots.fields.delete(source);
176
- if (sourceField.length === 0) {
177
- return; // Prevent creating 0 sized fields when inserting empty into empty.
178
- }
179
-
180
319
  const parent = this.getParent();
320
+ assert(
321
+ parent.mutableChunk !== this.forest.roots || parent.key !== source,
322
+ 0xd20 /* Attach source field must be different from current field */,
323
+ );
324
+ const sourceField = this.forest.roots.fields.get(source);
325
+ assert(sourceField !== undefined, 0xd21 /* Attach source field must exist */);
326
+ assert(
327
+ getFieldLength(sourceField) === count,
328
+ 0xd22 /* Attach must consume all nodes in source field */,
329
+ );
181
330
  const destinationField = getOrAddEmptyToMap(parent.mutableChunk.fields, parent.key);
331
+ assert(
332
+ destination <= getFieldLength(destinationField),
333
+ 0xd23 /* Attach destination must not exceed field length */,
334
+ );
182
335
  const destinationChunkIndex = splitFieldAtIndex(destinationField, destination, {
183
336
  policy: this.forest.chunker,
184
337
  idCompressor: this.forest.idCompressor,
185
338
  });
339
+ this.forest.roots.fields.delete(source);
186
340
  // TODO: this will fail for very large moves due to argument limits.
187
341
  destinationField.splice(destinationChunkIndex, 0, ...sourceField);
188
342
  },
@@ -203,7 +357,21 @@ export class ChunkedForest implements IEditableForest {
203
357
  this.forest.#events.emit("beforeChange");
204
358
  const parent = this.getParent();
205
359
  const sourceField = parent.mutableChunk.fields.get(parent.key) ?? [];
206
- assert(source.start <= source.end, 0xcf8 /* detach range start must not exceed end */);
360
+ assert(source.start <= source.end, 0xd24 /* Detach range start must not exceed end */);
361
+ assert(
362
+ source.end <= getFieldLength(sourceField),
363
+ 0xd25 /* Detach range must not exceed field length */,
364
+ );
365
+ if (destination !== undefined) {
366
+ assert(
367
+ parent.mutableChunk !== this.forest.roots || parent.key !== destination,
368
+ 0xd26 /* Detach destination field must be different from current field */,
369
+ );
370
+ assert(
371
+ !this.forest.roots.fields.has(destination),
372
+ 0xd27 /* Detach destination must be a new empty field */,
373
+ );
374
+ }
207
375
 
208
376
  const policy: ChunkCompressor = {
209
377
  policy: this.forest.chunker,
@@ -222,10 +390,6 @@ export class ChunkedForest implements IEditableForest {
222
390
  child.referenceRemoved();
223
391
  }
224
392
  } else {
225
- assert(
226
- !this.forest.roots.fields.has(destination),
227
- 0x7af /* Destination must be a new empty detached field */,
228
- );
229
393
  if (newField.length > 0) {
230
394
  this.forest.roots.fields.set(destination, newField);
231
395
  }
@@ -236,49 +400,24 @@ export class ChunkedForest implements IEditableForest {
236
400
  parent.mutableChunk.fields.delete(parent.key);
237
401
  }
238
402
  },
403
+ /**
404
+ * Ensure the selected node (by `index`) is an exclusively owned basic node,
405
+ * and store it under `this.mutableChunk`.
406
+ */
239
407
  enterNode(index: number): void {
240
408
  assert(this.mutableChunk === undefined, 0x535 /* should be in field */);
409
+
410
+ // Get the mutable parent, which we might have to modify to ensure the desired child is an exclusively owned (and thus mutable) BasicChunk.
241
411
  const parent = this.getParent();
412
+
413
+ // Lookup the current location of the node to be entered
242
414
  const chunks =
243
415
  parent.mutableChunk.fields.get(parent.key) ?? fail(0xaf6 /* missing edited field */);
244
- let indexWithinChunk = index;
245
- let indexOfChunk = 0;
246
- let chunk = chunks[indexOfChunk] ?? oob();
247
- while (indexWithinChunk >= chunk.topLevelLength) {
248
- indexWithinChunk -= chunk.topLevelLength;
249
- indexOfChunk++;
250
- if (indexOfChunk === chunks.length) {
251
- fail(0xaf7 /* missing edited node */);
252
- }
253
- chunk = chunks[indexOfChunk] ?? oob();
254
- }
255
- let found = chunks[indexOfChunk] ?? oob();
256
- if (!(found instanceof BasicChunk)) {
257
- // TODO:Perf: support in place editing of other chunk formats when possible:
258
- // 1. Support updating values in uniform chunks.
259
- // 2. Support traversing sequence chunks.
260
- //
261
- // Maybe build path when visitor navigates then lazily sync to chunk tree when editing?
262
- const newChunks = mapCursorField(found.cursor(), (cursor) =>
263
- basicChunkTree(cursor, {
264
- policy: this.forest.chunker,
265
- idCompressor: this.forest.idCompressor,
266
- }),
267
- );
268
- // TODO: this could fail for really long chunks being split (due to argument count limits).
269
- // Current implementations of chunks shouldn't ever be that long, but it could be an issue if they get bigger.
270
- chunks.splice(indexOfChunk, 1, ...newChunks);
271
- found.referenceRemoved();
272
416
 
273
- found = newChunks[indexWithinChunk] ?? oob();
274
- }
275
- assert(found instanceof BasicChunk, 0x536 /* chunk should have been normalized */);
276
- if (found.isShared()) {
277
- this.mutableChunk = chunks[indexOfChunk] = found.clone();
278
- found.referenceRemoved();
279
- } else {
280
- this.mutableChunk = found;
281
- }
417
+ this.mutableChunk = ensureExclusiveBasicChunk(chunks, index, {
418
+ policy: this.forest.chunker,
419
+ idCompressor: this.forest.idCompressor,
420
+ });
282
421
  },
283
422
  exitNode(index: number): void {
284
423
  assert(this.mutableChunk !== undefined, 0x537 /* should be in node */);
@@ -300,9 +439,12 @@ export class ChunkedForest implements IEditableForest {
300
439
  for (const getVisitor of this.deltaVisitors) {
301
440
  announcedVisitors.push(getVisitor());
302
441
  }
303
- const combinedVisitor = combineVisitors([forestVisitor, ...announcedVisitors]);
304
- this.activeVisitor = combinedVisitor;
305
- return combinedVisitor;
442
+ const visitor = combineVisitors([
443
+ makeBreakingVisitor(forestVisitor, this.breaker),
444
+ ...announcedVisitors,
445
+ ]);
446
+ this.activeVisitor = visitor;
447
+ return visitor;
306
448
  }
307
449
 
308
450
  private nextDetachedFieldIdentifier = 0;
@@ -317,6 +459,7 @@ export class ChunkedForest implements IEditableForest {
317
459
  }
318
460
 
319
461
  public allocateCursor(): Cursor {
462
+ this.breaker.use();
320
463
  return new Cursor(
321
464
  this,
322
465
  ITreeSubscriptionCursorState.Cleared,
@@ -337,6 +480,7 @@ export class ChunkedForest implements IEditableForest {
337
480
  destination: Anchor,
338
481
  cursorToMove: ITreeSubscriptionCursor,
339
482
  ): TreeNavigationResult {
483
+ this.breaker.use();
340
484
  const path = this.anchors.locate(destination);
341
485
  if (path === undefined) {
342
486
  return TreeNavigationResult.NotFound;
@@ -349,6 +493,7 @@ export class ChunkedForest implements IEditableForest {
349
493
  destination: FieldAnchor,
350
494
  cursorToMove: ITreeSubscriptionCursor,
351
495
  ): TreeNavigationResult {
496
+ this.breaker.use();
352
497
  assert(
353
498
  cursorToMove instanceof Cursor,
354
499
  0x53b /* ChunkedForest must only be given its own Cursor type */,
@@ -367,6 +512,7 @@ export class ChunkedForest implements IEditableForest {
367
512
  }
368
513
 
369
514
  public moveCursorToPath(destination: UpPath, cursorToMove: ITreeSubscriptionCursor): void {
515
+ this.breaker.use();
370
516
  assert(
371
517
  cursorToMove instanceof Cursor,
372
518
  0x53c /* ChunkedForest must only be given its own Cursor type */,
@@ -402,6 +548,7 @@ export class ChunkedForest implements IEditableForest {
402
548
  }
403
549
 
404
550
  public getCursorAboveDetachedFields(): ITreeCursorSynchronous {
551
+ this.breaker.use();
405
552
  const rootCursor = this.roots.cursor();
406
553
  rootCursor.enterNode(0);
407
554
  return rootCursor;
@@ -497,6 +644,14 @@ export function buildChunkedForest(
497
644
  chunker: IChunker,
498
645
  anchors?: AnchorSet,
499
646
  idCompressor?: IIdCompressor,
647
+ breaker?: Breakable,
500
648
  ): ChunkedForest {
501
- return new ChunkedForest(makeRoot(), chunker.schema, chunker, anchors, idCompressor);
649
+ return new ChunkedForest(
650
+ makeRoot(),
651
+ chunker.schema,
652
+ chunker,
653
+ anchors,
654
+ idCompressor,
655
+ breaker,
656
+ );
502
657
  }
@@ -22,7 +22,7 @@ import {
22
22
  combineVisitors,
23
23
  createAnnouncedVisitor,
24
24
  } from "../../core/index.js";
25
- import type { Breakable } from "../../util/index.js";
25
+ import { breakingMethod, type Breakable } from "../../util/index.js";
26
26
 
27
27
  import { assertForestsEqual } from "../treeTextCursor.js";
28
28
 
@@ -57,6 +57,7 @@ export class ComparisonForest implements IEditableForest {
57
57
  this.assertValid();
58
58
  }
59
59
 
60
+ @breakingMethod
60
61
  private assertValid(): void {
61
62
  assertForestsEqual(this.main, this.reference);
62
63
  }
@@ -73,6 +74,10 @@ export class ComparisonForest implements IEditableForest {
73
74
  return this.main.isEmpty;
74
75
  }
75
76
 
77
+ public get breaker(): Breakable {
78
+ return this.main.breaker;
79
+ }
80
+
76
81
  public clone(schema: TreeStoredSchemaSubscription, breaker?: Breakable): ComparisonForest {
77
82
  this.assertValid();
78
83
  return new ComparisonForest(
@@ -9,7 +9,7 @@ import type { IIdCompressor } from "@fluidframework/id-compressor";
9
9
  import type {
10
10
  IExperimentalIncrementalSummaryContext,
11
11
  ITelemetryContext,
12
- MinimumVersionForCollab,
12
+ OldestSupportedClientVersion,
13
13
  } from "@fluidframework/runtime-definitions/internal";
14
14
  import type { SummaryTreeBuilder } from "@fluidframework/runtime-utils/internal";
15
15
 
@@ -65,7 +65,7 @@ const supportedVersions = new Set<DetachedFieldIndexSummaryFormatVersion>([
65
65
  * Returns the summary version to use as per the given minimum version for collab.
66
66
  */
67
67
  function minVersionToDetachedFieldIndexSummaryFormatVersion(
68
- version: MinimumVersionForCollab,
68
+ version: OldestSupportedClientVersion,
69
69
  ): DetachedFieldIndexSummaryFormatVersion {
70
70
  // Currently, version 2 is written which adds metadata blob to the summary.
71
71
  return DetachedFieldIndexSummaryFormatVersion.v2;
@@ -32,8 +32,10 @@ import {
32
32
  type SummaryElementStringifier,
33
33
  } from "../../shared-tree-core/index.js";
34
34
  import {
35
+ breakingMethod,
35
36
  idAllocatorFromMaxId,
36
37
  readAndParseSnapshotBlob,
38
+ type Breakable,
37
39
  type JsonCompatibleReadOnly,
38
40
  } from "../../util/index.js";
39
41
  // eslint-disable-next-line import-x/no-internal-modules
@@ -70,6 +72,13 @@ export class ForestSummarizer
70
72
  {
71
73
  private readonly codec: ForestCodec;
72
74
 
75
+ /**
76
+ * This object is broken if and only if the forest it owns is broken.
77
+ */
78
+ public get breaker(): Breakable {
79
+ return this.forest.breaker;
80
+ }
81
+
73
82
  private readonly incrementalSummaryBuilder: ForestIncrementalSummaryBuilder;
74
83
  private readonly forestRootSummaryContentKey: string;
75
84
 
@@ -178,6 +187,7 @@ export class ForestSummarizer
178
187
  });
179
188
  }
180
189
 
190
+ @breakingMethod
181
191
  protected async loadInternal(
182
192
  services: IChannelStorageService,
183
193
  parse: SummaryElementParser,
@@ -3,7 +3,7 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import type { MinimumVersionForCollab } from "@fluidframework/runtime-definitions/internal";
6
+ import type { OldestSupportedClientVersion } from "@fluidframework/runtime-definitions/internal";
7
7
  import {
8
8
  getConfigForMinVersionForCollab,
9
9
  lowestMinVersionForCollab,
@@ -19,7 +19,7 @@ import { summaryContentBlobKey as summaryContentBlobKeyV3 } from "./summaryForma
19
19
  * Returns the summary format version to use as per the given minimum version for collab.
20
20
  */
21
21
  export function minVersionToForestSummaryFormatVersion(
22
- version: MinimumVersionForCollab,
22
+ version: OldestSupportedClientVersion,
23
23
  ): ForestSummaryFormatVersion {
24
24
  return getConfigForMinVersionForCollab(version, {
25
25
  [lowestMinVersionForCollab]: ForestSummaryFormatVersion.v2,
@@ -329,7 +329,7 @@ export class AnchorTreeIndex<TKey, TValue> implements TreeIndex<TKey, TValue> {
329
329
  if (errorMessage !== undefined) {
330
330
  throw new Error(errorMessage);
331
331
  }
332
- assert(false, 0xa8f /* invalid operation on a disposed index */);
332
+ fail(0xa8f /* invalid operation on a disposed index */);
333
333
  }
334
334
  }
335
335
 
@@ -3,7 +3,7 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { assert } from "@fluidframework/core-utils/internal";
6
+ import { assert, fail } from "@fluidframework/core-utils/internal";
7
7
  import {
8
8
  revisionMetadataSourceFromInfo,
9
9
  type ChangeAtomId,
@@ -289,7 +289,7 @@ class InvertManager extends CrossFieldManagerI<FieldChange> {
289
289
  id: ChangesetLocalId,
290
290
  count: number,
291
291
  ): void {
292
- assert(false, 0x9c5 /* Keys should not be moved manually during invert */);
292
+ fail(0x9c5 /* Keys should not be moved manually during invert */);
293
293
  }
294
294
 
295
295
  private get table(): InvertTable {
@@ -1673,30 +1673,9 @@ export function updateRefreshers(
1673
1673
  }
1674
1674
  }
1675
1675
 
1676
- const {
1677
- fieldChanges,
1678
- nodeChanges,
1679
- nodeToParent,
1680
- nodeAliases,
1681
- crossFieldKeys,
1682
- maxId,
1683
- revisions,
1684
- constraintViolationCount,
1685
- builds,
1686
- destroys,
1687
- } = change;
1688
-
1689
1676
  return makeModularChangeset({
1690
- fieldChanges,
1691
- nodeChanges,
1692
- nodeToParent,
1693
- nodeAliases,
1694
- crossFieldKeys,
1695
- maxId: maxId as number,
1696
- revisions,
1697
- constraintViolationCount,
1698
- builds,
1699
- destroys,
1677
+ ...change,
1678
+ maxId: change.maxId,
1700
1679
  refreshers,
1701
1680
  });
1702
1681
  }