@fluidframework/tree 2.115.0 → 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 (325) 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.js +1 -1
  67. package/dist/packageVersion.js.map +1 -1
  68. package/dist/shared-tree/independentView.d.ts.map +1 -1
  69. package/dist/shared-tree/independentView.js +2 -4
  70. package/dist/shared-tree/independentView.js.map +1 -1
  71. package/dist/shared-tree/sharedTree.d.ts +30 -5
  72. package/dist/shared-tree/sharedTree.d.ts.map +1 -1
  73. package/dist/shared-tree/sharedTree.js +8 -8
  74. package/dist/shared-tree/sharedTree.js.map +1 -1
  75. package/dist/shared-tree/sharedTreeChangeCodecs.d.ts +2 -2
  76. package/dist/shared-tree/sharedTreeChangeCodecs.d.ts.map +1 -1
  77. package/dist/shared-tree/sharedTreeChangeCodecs.js.map +1 -1
  78. package/dist/shared-tree/sharedTreeChangeEnricher.d.ts +25 -1
  79. package/dist/shared-tree/sharedTreeChangeEnricher.d.ts.map +1 -1
  80. package/dist/shared-tree/sharedTreeChangeEnricher.js +24 -0
  81. package/dist/shared-tree/sharedTreeChangeEnricher.js.map +1 -1
  82. package/dist/shared-tree/treeCheckout.d.ts +21 -10
  83. package/dist/shared-tree/treeCheckout.d.ts.map +1 -1
  84. package/dist/shared-tree/treeCheckout.js +48 -16
  85. package/dist/shared-tree/treeCheckout.js.map +1 -1
  86. package/dist/shared-tree-core/branchCommitEnricher.d.ts +2 -1
  87. package/dist/shared-tree-core/branchCommitEnricher.d.ts.map +1 -1
  88. package/dist/shared-tree-core/branchCommitEnricher.js +3 -2
  89. package/dist/shared-tree-core/branchCommitEnricher.js.map +1 -1
  90. package/dist/shared-tree-core/changeEnricher.d.ts +3 -2
  91. package/dist/shared-tree-core/changeEnricher.d.ts.map +1 -1
  92. package/dist/shared-tree-core/changeEnricher.js.map +1 -1
  93. package/dist/shared-tree-core/defaultResubmitMachine.d.ts +9 -1
  94. package/dist/shared-tree-core/defaultResubmitMachine.d.ts.map +1 -1
  95. package/dist/shared-tree-core/defaultResubmitMachine.js +7 -2
  96. package/dist/shared-tree-core/defaultResubmitMachine.js.map +1 -1
  97. package/dist/shared-tree-core/editManager.d.ts.map +1 -1
  98. package/dist/shared-tree-core/editManager.js +2 -2
  99. package/dist/shared-tree-core/editManager.js.map +1 -1
  100. package/dist/shared-tree-core/editManagerCodecs.d.ts +2 -2
  101. package/dist/shared-tree-core/editManagerCodecs.d.ts.map +1 -1
  102. package/dist/shared-tree-core/editManagerCodecs.js.map +1 -1
  103. package/dist/shared-tree-core/editManagerSummarizer.d.ts +2 -2
  104. package/dist/shared-tree-core/editManagerSummarizer.d.ts.map +1 -1
  105. package/dist/shared-tree-core/editManagerSummarizer.js.map +1 -1
  106. package/dist/shared-tree-core/messageCodecs.d.ts +2 -2
  107. package/dist/shared-tree-core/messageCodecs.d.ts.map +1 -1
  108. package/dist/shared-tree-core/messageCodecs.js.map +1 -1
  109. package/dist/shared-tree-core/sharedTreeCore.d.ts +11 -2
  110. package/dist/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
  111. package/dist/shared-tree-core/sharedTreeCore.js +11 -8
  112. package/dist/shared-tree-core/sharedTreeCore.js.map +1 -1
  113. package/dist/shared-tree-core/summaryTypes.d.ts +2 -2
  114. package/dist/shared-tree-core/summaryTypes.d.ts.map +1 -1
  115. package/dist/shared-tree-core/summaryTypes.js.map +1 -1
  116. package/dist/simple-tree/api/snapshotCompatibilityChecker.d.ts +1 -1
  117. package/dist/simple-tree/api/snapshotCompatibilityChecker.js.map +1 -1
  118. package/dist/simple-tree/api/storedSchema.d.ts +2 -2
  119. package/dist/simple-tree/api/storedSchema.d.ts.map +1 -1
  120. package/dist/simple-tree/api/storedSchema.js.map +1 -1
  121. package/dist/simple-tree/api/treeChangeEvents.d.ts +5 -1
  122. package/dist/simple-tree/api/treeChangeEvents.d.ts.map +1 -1
  123. package/dist/simple-tree/api/treeChangeEvents.js.map +1 -1
  124. package/dist/simple-tree/node-kinds/array/arrayNode.d.ts.map +1 -1
  125. package/dist/simple-tree/node-kinds/array/arrayNode.js +10 -0
  126. package/dist/simple-tree/node-kinds/array/arrayNode.js.map +1 -1
  127. package/dist/simple-tree/node-kinds/map/mapNode.d.ts.map +1 -1
  128. package/dist/simple-tree/node-kinds/map/mapNode.js +19 -2
  129. package/dist/simple-tree/node-kinds/map/mapNode.js.map +1 -1
  130. package/dist/tableSchema.d.ts +1 -1
  131. package/dist/tableSchema.js +1 -1
  132. package/dist/tableSchema.js.map +1 -1
  133. package/dist/treeFactory.d.ts.map +1 -1
  134. package/dist/treeFactory.js +1 -1
  135. package/dist/treeFactory.js.map +1 -1
  136. package/dist/util/breakable.d.ts +14 -2
  137. package/dist/util/breakable.d.ts.map +1 -1
  138. package/dist/util/breakable.js +9 -1
  139. package/dist/util/breakable.js.map +1 -1
  140. package/dist/util/compressedIds.d.ts +2 -2
  141. package/dist/util/compressedIds.d.ts.map +1 -1
  142. package/dist/util/compressedIds.js +1 -6
  143. package/dist/util/compressedIds.js.map +1 -1
  144. package/lib/codec/codec.d.ts +6 -6
  145. package/lib/codec/codec.d.ts.map +1 -1
  146. package/lib/codec/codec.js +3 -3
  147. package/lib/codec/codec.js.map +1 -1
  148. package/lib/codec/versioned/codec.d.ts +3 -3
  149. package/lib/codec/versioned/codec.d.ts.map +1 -1
  150. package/lib/codec/versioned/codec.js.map +1 -1
  151. package/lib/core/forest/editableForest.d.ts +2 -0
  152. package/lib/core/forest/editableForest.d.ts.map +1 -1
  153. package/lib/core/forest/editableForest.js.map +1 -1
  154. package/lib/core/index.d.ts +1 -1
  155. package/lib/core/index.d.ts.map +1 -1
  156. package/lib/core/index.js +1 -1
  157. package/lib/core/index.js.map +1 -1
  158. package/lib/core/tree/index.d.ts +1 -1
  159. package/lib/core/tree/index.d.ts.map +1 -1
  160. package/lib/core/tree/index.js +1 -1
  161. package/lib/core/tree/index.js.map +1 -1
  162. package/lib/core/tree/visitorUtils.d.ts +24 -3
  163. package/lib/core/tree/visitorUtils.d.ts.map +1 -1
  164. package/lib/core/tree/visitorUtils.js +22 -4
  165. package/lib/core/tree/visitorUtils.js.map +1 -1
  166. package/lib/feature-libraries/chunked-forest/chunkedForest.d.ts +30 -6
  167. package/lib/feature-libraries/chunked-forest/chunkedForest.d.ts.map +1 -1
  168. package/lib/feature-libraries/chunked-forest/chunkedForest.js +146 -56
  169. package/lib/feature-libraries/chunked-forest/chunkedForest.js.map +1 -1
  170. package/lib/feature-libraries/comparison-forest/comparisonForest.d.ts +2 -1
  171. package/lib/feature-libraries/comparison-forest/comparisonForest.d.ts.map +1 -1
  172. package/lib/feature-libraries/comparison-forest/comparisonForest.js +88 -70
  173. package/lib/feature-libraries/comparison-forest/comparisonForest.js.map +1 -1
  174. package/lib/feature-libraries/detachedFieldIndexSummarizer.js.map +1 -1
  175. package/lib/feature-libraries/forest-summary/forestSummarizer.d.ts +5 -0
  176. package/lib/feature-libraries/forest-summary/forestSummarizer.d.ts.map +1 -1
  177. package/lib/feature-libraries/forest-summary/forestSummarizer.js +129 -108
  178. package/lib/feature-libraries/forest-summary/forestSummarizer.js.map +1 -1
  179. package/lib/feature-libraries/forest-summary/summaryTypes.d.ts +2 -2
  180. package/lib/feature-libraries/forest-summary/summaryTypes.d.ts.map +1 -1
  181. package/lib/feature-libraries/forest-summary/summaryTypes.js.map +1 -1
  182. package/lib/feature-libraries/indexing/anchorTreeIndex.js +1 -1
  183. package/lib/feature-libraries/indexing/anchorTreeIndex.js.map +1 -1
  184. package/lib/feature-libraries/modular-schema/invert.js +2 -2
  185. package/lib/feature-libraries/modular-schema/invert.js.map +1 -1
  186. package/lib/feature-libraries/modular-schema/modularChangeFamily.d.ts.map +1 -1
  187. package/lib/feature-libraries/modular-schema/modularChangeFamily.js +2 -11
  188. package/lib/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
  189. package/lib/feature-libraries/modular-schema/modularChangeUtils.d.ts +11 -16
  190. package/lib/feature-libraries/modular-schema/modularChangeUtils.d.ts.map +1 -1
  191. package/lib/feature-libraries/modular-schema/modularChangeUtils.js +10 -3
  192. package/lib/feature-libraries/modular-schema/modularChangeUtils.js.map +1 -1
  193. package/lib/feature-libraries/object-forest/objectForest.d.ts.map +1 -1
  194. package/lib/feature-libraries/object-forest/objectForest.js +35 -14
  195. package/lib/feature-libraries/object-forest/objectForest.js.map +1 -1
  196. package/lib/feature-libraries/schema-index/schemaSummarizer.d.ts +2 -2
  197. package/lib/feature-libraries/schema-index/schemaSummarizer.d.ts.map +1 -1
  198. package/lib/feature-libraries/schema-index/schemaSummarizer.js.map +1 -1
  199. package/lib/feature-libraries/sequence-field/rebase.js +2 -2
  200. package/lib/feature-libraries/sequence-field/rebase.js.map +1 -1
  201. package/lib/feature-libraries/sequence-field/utils.js +1 -1
  202. package/lib/feature-libraries/sequence-field/utils.js.map +1 -1
  203. package/lib/packageVersion.d.ts +1 -1
  204. package/lib/packageVersion.js +1 -1
  205. package/lib/packageVersion.js.map +1 -1
  206. package/lib/shared-tree/independentView.d.ts.map +1 -1
  207. package/lib/shared-tree/independentView.js +3 -5
  208. package/lib/shared-tree/independentView.js.map +1 -1
  209. package/lib/shared-tree/sharedTree.d.ts +30 -5
  210. package/lib/shared-tree/sharedTree.d.ts.map +1 -1
  211. package/lib/shared-tree/sharedTree.js +8 -8
  212. package/lib/shared-tree/sharedTree.js.map +1 -1
  213. package/lib/shared-tree/sharedTreeChangeCodecs.d.ts +2 -2
  214. package/lib/shared-tree/sharedTreeChangeCodecs.d.ts.map +1 -1
  215. package/lib/shared-tree/sharedTreeChangeCodecs.js.map +1 -1
  216. package/lib/shared-tree/sharedTreeChangeEnricher.d.ts +25 -1
  217. package/lib/shared-tree/sharedTreeChangeEnricher.d.ts.map +1 -1
  218. package/lib/shared-tree/sharedTreeChangeEnricher.js +24 -0
  219. package/lib/shared-tree/sharedTreeChangeEnricher.js.map +1 -1
  220. package/lib/shared-tree/treeCheckout.d.ts +21 -10
  221. package/lib/shared-tree/treeCheckout.d.ts.map +1 -1
  222. package/lib/shared-tree/treeCheckout.js +48 -16
  223. package/lib/shared-tree/treeCheckout.js.map +1 -1
  224. package/lib/shared-tree-core/branchCommitEnricher.d.ts +2 -1
  225. package/lib/shared-tree-core/branchCommitEnricher.d.ts.map +1 -1
  226. package/lib/shared-tree-core/branchCommitEnricher.js +3 -2
  227. package/lib/shared-tree-core/branchCommitEnricher.js.map +1 -1
  228. package/lib/shared-tree-core/changeEnricher.d.ts +3 -2
  229. package/lib/shared-tree-core/changeEnricher.d.ts.map +1 -1
  230. package/lib/shared-tree-core/changeEnricher.js.map +1 -1
  231. package/lib/shared-tree-core/defaultResubmitMachine.d.ts +9 -1
  232. package/lib/shared-tree-core/defaultResubmitMachine.d.ts.map +1 -1
  233. package/lib/shared-tree-core/defaultResubmitMachine.js +7 -2
  234. package/lib/shared-tree-core/defaultResubmitMachine.js.map +1 -1
  235. package/lib/shared-tree-core/editManager.d.ts.map +1 -1
  236. package/lib/shared-tree-core/editManager.js +2 -2
  237. package/lib/shared-tree-core/editManager.js.map +1 -1
  238. package/lib/shared-tree-core/editManagerCodecs.d.ts +2 -2
  239. package/lib/shared-tree-core/editManagerCodecs.d.ts.map +1 -1
  240. package/lib/shared-tree-core/editManagerCodecs.js.map +1 -1
  241. package/lib/shared-tree-core/editManagerSummarizer.d.ts +2 -2
  242. package/lib/shared-tree-core/editManagerSummarizer.d.ts.map +1 -1
  243. package/lib/shared-tree-core/editManagerSummarizer.js.map +1 -1
  244. package/lib/shared-tree-core/messageCodecs.d.ts +2 -2
  245. package/lib/shared-tree-core/messageCodecs.d.ts.map +1 -1
  246. package/lib/shared-tree-core/messageCodecs.js.map +1 -1
  247. package/lib/shared-tree-core/sharedTreeCore.d.ts +11 -2
  248. package/lib/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
  249. package/lib/shared-tree-core/sharedTreeCore.js +11 -8
  250. package/lib/shared-tree-core/sharedTreeCore.js.map +1 -1
  251. package/lib/shared-tree-core/summaryTypes.d.ts +2 -2
  252. package/lib/shared-tree-core/summaryTypes.d.ts.map +1 -1
  253. package/lib/shared-tree-core/summaryTypes.js.map +1 -1
  254. package/lib/simple-tree/api/snapshotCompatibilityChecker.d.ts +1 -1
  255. package/lib/simple-tree/api/snapshotCompatibilityChecker.js.map +1 -1
  256. package/lib/simple-tree/api/storedSchema.d.ts +2 -2
  257. package/lib/simple-tree/api/storedSchema.d.ts.map +1 -1
  258. package/lib/simple-tree/api/storedSchema.js.map +1 -1
  259. package/lib/simple-tree/api/treeChangeEvents.d.ts +5 -1
  260. package/lib/simple-tree/api/treeChangeEvents.d.ts.map +1 -1
  261. package/lib/simple-tree/api/treeChangeEvents.js.map +1 -1
  262. package/lib/simple-tree/node-kinds/array/arrayNode.d.ts.map +1 -1
  263. package/lib/simple-tree/node-kinds/array/arrayNode.js +10 -0
  264. package/lib/simple-tree/node-kinds/array/arrayNode.js.map +1 -1
  265. package/lib/simple-tree/node-kinds/map/mapNode.d.ts.map +1 -1
  266. package/lib/simple-tree/node-kinds/map/mapNode.js +19 -2
  267. package/lib/simple-tree/node-kinds/map/mapNode.js.map +1 -1
  268. package/lib/tableSchema.d.ts +1 -1
  269. package/lib/tableSchema.js +1 -1
  270. package/lib/tableSchema.js.map +1 -1
  271. package/lib/treeFactory.d.ts.map +1 -1
  272. package/lib/treeFactory.js +1 -1
  273. package/lib/treeFactory.js.map +1 -1
  274. package/lib/util/breakable.d.ts +14 -2
  275. package/lib/util/breakable.d.ts.map +1 -1
  276. package/lib/util/breakable.js +9 -1
  277. package/lib/util/breakable.js.map +1 -1
  278. package/lib/util/compressedIds.d.ts +2 -2
  279. package/lib/util/compressedIds.d.ts.map +1 -1
  280. package/lib/util/compressedIds.js +1 -6
  281. package/lib/util/compressedIds.js.map +1 -1
  282. package/package.json +27 -27
  283. package/src/codec/codec.ts +7 -7
  284. package/src/codec/versioned/codec.ts +5 -5
  285. package/src/core/forest/editableForest.ts +2 -0
  286. package/src/core/index.ts +1 -1
  287. package/src/core/tree/index.ts +1 -1
  288. package/src/core/tree/visitorUtils.ts +37 -12
  289. package/src/feature-libraries/chunked-forest/chunkedForest.ts +214 -59
  290. package/src/feature-libraries/comparison-forest/comparisonForest.ts +6 -1
  291. package/src/feature-libraries/detachedFieldIndexSummarizer.ts +2 -2
  292. package/src/feature-libraries/forest-summary/forestSummarizer.ts +10 -0
  293. package/src/feature-libraries/forest-summary/summaryTypes.ts +2 -2
  294. package/src/feature-libraries/indexing/anchorTreeIndex.ts +1 -1
  295. package/src/feature-libraries/modular-schema/invert.ts +2 -2
  296. package/src/feature-libraries/modular-schema/modularChangeFamily.ts +2 -23
  297. package/src/feature-libraries/modular-schema/modularChangeUtils.ts +12 -21
  298. package/src/feature-libraries/object-forest/objectForest.ts +48 -14
  299. package/src/feature-libraries/schema-index/schemaSummarizer.ts +3 -3
  300. package/src/feature-libraries/sequence-field/rebase.ts +2 -2
  301. package/src/feature-libraries/sequence-field/utils.ts +1 -1
  302. package/src/packageVersion.ts +1 -1
  303. package/src/shared-tree/independentView.ts +5 -12
  304. package/src/shared-tree/sharedTree.ts +41 -10
  305. package/src/shared-tree/sharedTreeChangeCodecs.ts +2 -2
  306. package/src/shared-tree/sharedTreeChangeEnricher.ts +25 -1
  307. package/src/shared-tree/treeCheckout.ts +45 -16
  308. package/src/shared-tree-core/branchCommitEnricher.ts +6 -2
  309. package/src/shared-tree-core/changeEnricher.ts +7 -2
  310. package/src/shared-tree-core/defaultResubmitMachine.ts +5 -0
  311. package/src/shared-tree-core/editManager.ts +2 -4
  312. package/src/shared-tree-core/editManagerCodecs.ts +2 -2
  313. package/src/shared-tree-core/editManagerSummarizer.ts +3 -3
  314. package/src/shared-tree-core/messageCodecs.ts +2 -2
  315. package/src/shared-tree-core/sharedTreeCore.ts +29 -11
  316. package/src/shared-tree-core/summaryTypes.ts +2 -2
  317. package/src/simple-tree/api/snapshotCompatibilityChecker.ts +1 -1
  318. package/src/simple-tree/api/storedSchema.ts +2 -2
  319. package/src/simple-tree/api/treeChangeEvents.ts +5 -1
  320. package/src/simple-tree/node-kinds/array/arrayNode.ts +15 -0
  321. package/src/simple-tree/node-kinds/map/mapNode.ts +23 -2
  322. package/src/tableSchema.ts +1 -1
  323. package/src/treeFactory.ts +0 -1
  324. package/src/util/breakable.ts +9 -1
  325. package/src/util/compressedIds.ts +7 -13
@@ -13,10 +13,28 @@ export function applyDelta(delta, latestRevision, deltaProcessor, detachedFieldI
13
13
  visitDelta(delta, visitor, detachedFieldIndex, latestRevision);
14
14
  visitor.free();
15
15
  }
16
- export function announceDelta(delta, latestRevision, deltaProcessor, detachedFieldIndex) {
17
- const visitor = deltaProcessor.acquireVisitor();
18
- visitDelta(delta, combineVisitors([visitor]), detachedFieldIndex, latestRevision);
19
- visitor.free();
16
+ /**
17
+ * Wraps a visitor so any error breaks the supplied scope and all subsequent calls fail.
18
+ *
19
+ * @remarks
20
+ * The `{ readonly type?: never }` intersection restricts this helper to plain visitors. Wrapping
21
+ * an {@link AnnouncedVisitor} or {@link CombinedVisitor} as a plain visitor would hide its `type`
22
+ * discriminator and prevent {@link combineVisitors} from preserving announced-event ordering or
23
+ * flattening nested combined visitors.
24
+ */
25
+ export function makeBreakingVisitor(visitor, breaker) {
26
+ return {
27
+ free: () => breaker.run(() => visitor.free()),
28
+ create: (...args) => breaker.run(() => visitor.create(...args)),
29
+ destroy: (...args) => breaker.run(() => visitor.destroy(...args)),
30
+ attach: (...args) => breaker.run(() => visitor.attach(...args)),
31
+ detach: (...args) => breaker.run(() => visitor.detach(...args)),
32
+ enterNode: (...args) => breaker.run(() => visitor.enterNode(...args)),
33
+ exitNode: (...args) => breaker.run(() => visitor.exitNode(...args)),
34
+ enterField: (...args) => breaker.run(() => visitor.enterField(...args)),
35
+ exitField: (...args) => breaker.run(() => visitor.exitField(...args)),
36
+ fieldMarks: (...args) => breaker.run(() => visitor.fieldMarks?.(...args)),
37
+ };
20
38
  }
21
39
  /**
22
40
  * Combines multiple visitors into a single visitor.
@@ -1 +1 @@
1
- {"version":3,"file":"visitorUtils.js","sourceRoot":"","sources":["../../../src/core/tree/visitorUtils.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 { type IdAllocator, idAllocatorFromMaxId } from \"../../util/index.js\";\nimport type { RevisionTag } from \"../rebase/index.js\";\nimport type { FieldKey } from \"../schema-stored/index.js\";\n\nimport type { ITreeCursorSynchronous } from \"./cursor.js\";\nimport type { DetachedNodeId, Root } from \"./delta.js\";\nimport { DetachedFieldIndex } from \"./detachedFieldIndex.js\";\nimport type { ForestRootId } from \"./detachedFieldIndexTypes.js\";\nimport type { PlaceIndex, Range } from \"./pathTree.js\";\nimport { type DeltaVisitor, visitDelta } from \"./visitDelta.js\";\n\nexport function makeDetachedFieldIndex(prefix: string = \"Temp\"): DetachedFieldIndex {\n\treturn new DetachedFieldIndex(prefix, idAllocatorFromMaxId() as IdAllocator<ForestRootId>);\n}\n\nexport function applyDelta(\n\tdelta: Root,\n\tlatestRevision: RevisionTag | undefined,\n\tdeltaProcessor: { acquireVisitor: () => DeltaVisitor },\n\tdetachedFieldIndex: DetachedFieldIndex,\n): void {\n\tconst visitor = deltaProcessor.acquireVisitor();\n\tvisitDelta(delta, visitor, detachedFieldIndex, latestRevision);\n\tvisitor.free();\n}\n\nexport function announceDelta(\n\tdelta: Root,\n\tlatestRevision: RevisionTag | undefined,\n\tdeltaProcessor: { acquireVisitor: () => DeltaVisitor & AnnouncedVisitor },\n\tdetachedFieldIndex: DetachedFieldIndex,\n): void {\n\tconst visitor = deltaProcessor.acquireVisitor();\n\tvisitDelta(delta, combineVisitors([visitor]), detachedFieldIndex, latestRevision);\n\tvisitor.free();\n}\n\nexport interface CombinedVisitor extends DeltaVisitor {\n\treadonly type: \"Combined\";\n\n\treadonly visitors: readonly CombinableVisitor[];\n}\n\nexport type CombinableVisitor =\n\t| (DeltaVisitor & { type?: never })\n\t| AnnouncedVisitor\n\t| CombinedVisitor;\n\n/**\n * Combines multiple visitors into a single visitor.\n * @param visitors - The returned visitor invokes the corresponding events for all these visitors, in order.\n * @returns a DeltaVisitor combining all `visitors`.\n */\nexport function combineVisitors(visitors: readonly CombinableVisitor[]): CombinedVisitor {\n\tconst allVisitors = visitors.flatMap((v) => (v.type === \"Combined\" ? v.visitors : [v]));\n\tconst announcedVisitors = allVisitors.filter(\n\t\t(v): v is AnnouncedVisitor => v.type === \"Announced\",\n\t);\n\treturn {\n\t\ttype: \"Combined\",\n\t\tvisitors: allVisitors,\n\t\tfree: () => {\n\t\t\tfor (const v of visitors) {\n\t\t\t\tv.free();\n\t\t\t}\n\t\t},\n\t\tcreate: (...args) => {\n\t\t\tfor (const v of allVisitors) {\n\t\t\t\tv.create(...args);\n\t\t\t}\n\t\t\tfor (const v of announcedVisitors) {\n\t\t\t\tv.afterCreate(...args);\n\t\t\t}\n\t\t},\n\t\tdestroy: (...args) => {\n\t\t\tfor (const v of announcedVisitors) {\n\t\t\t\tv.beforeDestroy(...args);\n\t\t\t}\n\t\t\tfor (const v of allVisitors) {\n\t\t\t\tv.destroy(...args);\n\t\t\t}\n\t\t},\n\t\tattach: (source: FieldKey, count: number, destination: PlaceIndex) => {\n\t\t\tfor (const v of announcedVisitors) {\n\t\t\t\tv.beforeAttach(source, count, destination);\n\t\t\t}\n\t\t\tfor (const v of allVisitors) {\n\t\t\t\tv.attach(source, count, destination);\n\t\t\t}\n\t\t\tfor (const v of announcedVisitors) {\n\t\t\t\tv.afterAttach(source, {\n\t\t\t\t\tstart: destination,\n\t\t\t\t\tend: destination + count,\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\tdetach: (\n\t\t\tsource: Range,\n\t\t\tdestination: FieldKey,\n\t\t\tid: DetachedNodeId,\n\t\t\tisReplaced: boolean,\n\t\t) => {\n\t\t\tfor (const v of announcedVisitors) {\n\t\t\t\tv.beforeDetach(source, destination, isReplaced);\n\t\t\t}\n\t\t\tfor (const v of allVisitors) {\n\t\t\t\tv.detach(source, destination, id, isReplaced);\n\t\t\t}\n\t\t\tfor (const v of announcedVisitors) {\n\t\t\t\tv.afterDetach(source.start, source.end - source.start, destination, isReplaced);\n\t\t\t}\n\t\t},\n\t\tenterNode: (...args) => {\n\t\t\tfor (const v of allVisitors) {\n\t\t\t\tv.enterNode(...args);\n\t\t\t}\n\t\t},\n\t\texitNode: (...args) => {\n\t\t\tfor (const v of allVisitors) {\n\t\t\t\tv.exitNode(...args);\n\t\t\t}\n\t\t},\n\t\tenterField: (...args) => {\n\t\t\tfor (const v of allVisitors) {\n\t\t\t\tv.enterField(...args);\n\t\t\t}\n\t\t},\n\t\texitField: (...args) => {\n\t\t\tfor (const v of allVisitors) {\n\t\t\t\tv.exitField(...args);\n\t\t\t}\n\t\t},\n\t\tfieldMarks: (marks) => {\n\t\t\tfor (const v of allVisitors) {\n\t\t\t\tv.fieldMarks?.(marks);\n\t\t\t}\n\t\t},\n\t};\n}\n\n/**\n * Visitor that is notified of changes before, after, and when changes are made.\n * Must be freed after use.\n */\nexport interface AnnouncedVisitor extends DeltaVisitor {\n\treadonly type: \"Announced\";\n\t/**\n\t * A hook that is called after all nodes have been created.\n\t */\n\tafterCreate(content: readonly ITreeCursorSynchronous[], destination: FieldKey): void;\n\tbeforeDestroy(field: FieldKey, count: number): void;\n\tbeforeAttach(source: FieldKey, count: number, destination: PlaceIndex): void;\n\tafterAttach(source: FieldKey, destination: Range): void;\n\tbeforeDetach(source: Range, destination: FieldKey, isReplaced: boolean): void;\n\tafterDetach(\n\t\tsource: PlaceIndex,\n\t\tcount: number,\n\t\tdestination: FieldKey,\n\t\tisReplaced: boolean,\n\t): void;\n}\n\nconst noOp = (): void => {};\n\n/**\n * Creates an announced visitor with only the provided functions and uses a no op for the rest.\n * This is provided to make some of the delta visitor definitions cleaner.\n */\nexport function createAnnouncedVisitor(\n\tvisitorFunctions: Partial<AnnouncedVisitor>,\n): AnnouncedVisitor {\n\treturn {\n\t\ttype: \"Announced\",\n\t\tfree: visitorFunctions.free ?? noOp,\n\t\tcreate: visitorFunctions.create ?? noOp,\n\t\tafterCreate: visitorFunctions.afterCreate ?? noOp,\n\t\tbeforeDestroy: visitorFunctions.beforeDestroy ?? noOp,\n\t\tdestroy: visitorFunctions.destroy ?? noOp,\n\t\tbeforeAttach: visitorFunctions.beforeAttach ?? noOp,\n\t\tattach: visitorFunctions.attach ?? noOp,\n\t\tafterAttach: visitorFunctions.afterAttach ?? noOp,\n\t\tbeforeDetach: visitorFunctions.beforeDetach ?? noOp,\n\t\tdetach: visitorFunctions.detach ?? noOp,\n\t\tafterDetach: visitorFunctions.afterDetach ?? noOp,\n\t\tenterNode: visitorFunctions.enterNode ?? noOp,\n\t\texitNode: visitorFunctions.exitNode ?? noOp,\n\t\tenterField: visitorFunctions.enterField ?? noOp,\n\t\texitField: visitorFunctions.exitField ?? noOp,\n\t};\n}\n"]}
1
+ {"version":3,"file":"visitorUtils.js","sourceRoot":"","sources":["../../../src/core/tree/visitorUtils.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 { type Breakable, type IdAllocator, idAllocatorFromMaxId } from \"../../util/index.js\";\nimport type { RevisionTag } from \"../rebase/index.js\";\nimport type { FieldKey } from \"../schema-stored/index.js\";\n\nimport type { ITreeCursorSynchronous } from \"./cursor.js\";\nimport type { DetachedNodeId, Root } from \"./delta.js\";\nimport { DetachedFieldIndex } from \"./detachedFieldIndex.js\";\nimport type { ForestRootId } from \"./detachedFieldIndexTypes.js\";\nimport type { PlaceIndex, Range } from \"./pathTree.js\";\nimport { type DeltaVisitor, visitDelta } from \"./visitDelta.js\";\n\nexport function makeDetachedFieldIndex(prefix: string = \"Temp\"): DetachedFieldIndex {\n\treturn new DetachedFieldIndex(prefix, idAllocatorFromMaxId() as IdAllocator<ForestRootId>);\n}\n\nexport function applyDelta(\n\tdelta: Root,\n\tlatestRevision: RevisionTag | undefined,\n\tdeltaProcessor: { acquireVisitor: () => DeltaVisitor },\n\tdetachedFieldIndex: DetachedFieldIndex,\n): void {\n\tconst visitor = deltaProcessor.acquireVisitor();\n\tvisitDelta(delta, visitor, detachedFieldIndex, latestRevision);\n\tvisitor.free();\n}\n\nexport interface CombinedVisitor extends DeltaVisitor {\n\treadonly type: \"Combined\";\n\n\treadonly visitors: readonly CombinableVisitor[];\n}\n\n/**\n * A visitor accepted by {@link combineVisitors}.\n *\n * @remarks\n * Plain {@link DeltaVisitor}s are intersected with `{ readonly type?: never }` so this forms a\n * discriminated union with {@link AnnouncedVisitor} and {@link CombinedVisitor}. The optional\n * `never` property permits visitors without a `type`, while preventing a visitor with an unknown\n * or widened `type` from being treated as plain and losing its specialized composition behavior.\n */\nexport type CombinableVisitor =\n\t| (DeltaVisitor & { type?: never })\n\t| AnnouncedVisitor\n\t| CombinedVisitor;\n\n/**\n * Wraps a visitor so any error breaks the supplied scope and all subsequent calls fail.\n *\n * @remarks\n * The `{ readonly type?: never }` intersection restricts this helper to plain visitors. Wrapping\n * an {@link AnnouncedVisitor} or {@link CombinedVisitor} as a plain visitor would hide its `type`\n * discriminator and prevent {@link combineVisitors} from preserving announced-event ordering or\n * flattening nested combined visitors.\n */\nexport function makeBreakingVisitor(\n\tvisitor: DeltaVisitor & { readonly type?: never },\n\tbreaker: Breakable,\n): DeltaVisitor & { readonly type?: never } {\n\treturn {\n\t\tfree: () => breaker.run(() => visitor.free()),\n\t\tcreate: (...args) => breaker.run(() => visitor.create(...args)),\n\t\tdestroy: (...args) => breaker.run(() => visitor.destroy(...args)),\n\t\tattach: (...args) => breaker.run(() => visitor.attach(...args)),\n\t\tdetach: (...args) => breaker.run(() => visitor.detach(...args)),\n\t\tenterNode: (...args) => breaker.run(() => visitor.enterNode(...args)),\n\t\texitNode: (...args) => breaker.run(() => visitor.exitNode(...args)),\n\t\tenterField: (...args) => breaker.run(() => visitor.enterField(...args)),\n\t\texitField: (...args) => breaker.run(() => visitor.exitField(...args)),\n\t\tfieldMarks: (...args) => breaker.run(() => visitor.fieldMarks?.(...args)),\n\t};\n}\n\n/**\n * Combines multiple visitors into a single visitor.\n * @param visitors - The returned visitor invokes the corresponding events for all these visitors, in order.\n * @returns a DeltaVisitor combining all `visitors`.\n */\nexport function combineVisitors(visitors: readonly CombinableVisitor[]): CombinedVisitor {\n\tconst allVisitors = visitors.flatMap((v) => (v.type === \"Combined\" ? v.visitors : [v]));\n\tconst announcedVisitors = allVisitors.filter(\n\t\t(v): v is AnnouncedVisitor => v.type === \"Announced\",\n\t);\n\treturn {\n\t\ttype: \"Combined\",\n\t\tvisitors: allVisitors,\n\t\tfree: () => {\n\t\t\tfor (const v of visitors) {\n\t\t\t\tv.free();\n\t\t\t}\n\t\t},\n\t\tcreate: (...args) => {\n\t\t\tfor (const v of allVisitors) {\n\t\t\t\tv.create(...args);\n\t\t\t}\n\t\t\tfor (const v of announcedVisitors) {\n\t\t\t\tv.afterCreate(...args);\n\t\t\t}\n\t\t},\n\t\tdestroy: (...args) => {\n\t\t\tfor (const v of announcedVisitors) {\n\t\t\t\tv.beforeDestroy(...args);\n\t\t\t}\n\t\t\tfor (const v of allVisitors) {\n\t\t\t\tv.destroy(...args);\n\t\t\t}\n\t\t},\n\t\tattach: (source: FieldKey, count: number, destination: PlaceIndex) => {\n\t\t\tfor (const v of announcedVisitors) {\n\t\t\t\tv.beforeAttach(source, count, destination);\n\t\t\t}\n\t\t\tfor (const v of allVisitors) {\n\t\t\t\tv.attach(source, count, destination);\n\t\t\t}\n\t\t\tfor (const v of announcedVisitors) {\n\t\t\t\tv.afterAttach(source, {\n\t\t\t\t\tstart: destination,\n\t\t\t\t\tend: destination + count,\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\tdetach: (\n\t\t\tsource: Range,\n\t\t\tdestination: FieldKey,\n\t\t\tid: DetachedNodeId,\n\t\t\tisReplaced: boolean,\n\t\t) => {\n\t\t\tfor (const v of announcedVisitors) {\n\t\t\t\tv.beforeDetach(source, destination, isReplaced);\n\t\t\t}\n\t\t\tfor (const v of allVisitors) {\n\t\t\t\tv.detach(source, destination, id, isReplaced);\n\t\t\t}\n\t\t\tfor (const v of announcedVisitors) {\n\t\t\t\tv.afterDetach(source.start, source.end - source.start, destination, isReplaced);\n\t\t\t}\n\t\t},\n\t\tenterNode: (...args) => {\n\t\t\tfor (const v of allVisitors) {\n\t\t\t\tv.enterNode(...args);\n\t\t\t}\n\t\t},\n\t\texitNode: (...args) => {\n\t\t\tfor (const v of allVisitors) {\n\t\t\t\tv.exitNode(...args);\n\t\t\t}\n\t\t},\n\t\tenterField: (...args) => {\n\t\t\tfor (const v of allVisitors) {\n\t\t\t\tv.enterField(...args);\n\t\t\t}\n\t\t},\n\t\texitField: (...args) => {\n\t\t\tfor (const v of allVisitors) {\n\t\t\t\tv.exitField(...args);\n\t\t\t}\n\t\t},\n\t\tfieldMarks: (marks) => {\n\t\t\tfor (const v of allVisitors) {\n\t\t\t\tv.fieldMarks?.(marks);\n\t\t\t}\n\t\t},\n\t};\n}\n\n/**\n * Visitor that is notified of changes before, after, and when changes are made.\n * Must be freed after use.\n */\nexport interface AnnouncedVisitor extends DeltaVisitor {\n\treadonly type: \"Announced\";\n\t/**\n\t * A hook that is called after all nodes have been created.\n\t */\n\tafterCreate(content: readonly ITreeCursorSynchronous[], destination: FieldKey): void;\n\tbeforeDestroy(field: FieldKey, count: number): void;\n\tbeforeAttach(source: FieldKey, count: number, destination: PlaceIndex): void;\n\tafterAttach(source: FieldKey, destination: Range): void;\n\tbeforeDetach(source: Range, destination: FieldKey, isReplaced: boolean): void;\n\tafterDetach(\n\t\tsource: PlaceIndex,\n\t\tcount: number,\n\t\tdestination: FieldKey,\n\t\tisReplaced: boolean,\n\t): void;\n}\n\nconst noOp = (): void => {};\n\n/**\n * Creates an announced visitor with only the provided functions and uses a no op for the rest.\n * This is provided to make some of the delta visitor definitions cleaner.\n */\nexport function createAnnouncedVisitor(\n\tvisitorFunctions: Partial<AnnouncedVisitor>,\n): AnnouncedVisitor {\n\treturn {\n\t\ttype: \"Announced\",\n\t\tfree: visitorFunctions.free ?? noOp,\n\t\tcreate: visitorFunctions.create ?? noOp,\n\t\tafterCreate: visitorFunctions.afterCreate ?? noOp,\n\t\tbeforeDestroy: visitorFunctions.beforeDestroy ?? noOp,\n\t\tdestroy: visitorFunctions.destroy ?? noOp,\n\t\tbeforeAttach: visitorFunctions.beforeAttach ?? noOp,\n\t\tattach: visitorFunctions.attach ?? noOp,\n\t\tafterAttach: visitorFunctions.afterAttach ?? noOp,\n\t\tbeforeDetach: visitorFunctions.beforeDetach ?? noOp,\n\t\tdetach: visitorFunctions.detach ?? noOp,\n\t\tafterDetach: visitorFunctions.afterDetach ?? noOp,\n\t\tenterNode: visitorFunctions.enterNode ?? noOp,\n\t\texitNode: visitorFunctions.exitNode ?? noOp,\n\t\tenterField: visitorFunctions.enterField ?? noOp,\n\t\texitField: visitorFunctions.exitField ?? noOp,\n\t};\n}\n"]}
@@ -5,21 +5,45 @@
5
5
  import type { Listenable } from "@fluidframework/core-interfaces";
6
6
  import type { IIdCompressor } from "@fluidframework/id-compressor";
7
7
  import { type Anchor, AnchorSet, type AnnouncedVisitor, type DeltaVisitor, type DetachedField, type FieldAnchor, type FieldKey, type ForestEvents, type IEditableForest, type ITreeCursorSynchronous, type ITreeSubscriptionCursor, ITreeSubscriptionCursorState, TreeNavigationResult, type TreeStoredSchemaSubscription, type UpPath, type ChunkedCursor, type TreeChunk } from "../../core/index.js";
8
- import { type Breakable } from "../../util/index.js";
8
+ import { Breakable, type WithBreakable } from "../../util/index.js";
9
9
  import { BasicChunk, BasicChunkCursor, type SiblingsOrKey } from "./basicChunk.js";
10
- import { type IChunker } from "./chunkTree.js";
10
+ import { type ChunkCompressor, type IChunker } from "./chunkTree.js";
11
+ /**
12
+ * Locates a top-level node within a field's chunk representation.
13
+ * @param chunks - The chunks representing the field.
14
+ * @param index - The node index within the field.
15
+ * @returns The containing chunk, its array index, and the node's offset within it.
16
+ */
17
+ export declare function locateNodeInChunks(chunks: readonly TreeChunk[], index: number): {
18
+ chunk: TreeChunk;
19
+ indexOfChunk: number;
20
+ indexWithinChunk: number;
21
+ };
22
+ /**
23
+ * Ensures the node at index `index` within the field represented by `chunks` is contained in a non-shared {@link BasicChunk}.
24
+ *
25
+ * @param chunks - The chunks representing the field which will be modified to ensure the node at
26
+ * `index` is in a non-shared {@link BasicChunk}.
27
+ * @param index - The node index within the field.
28
+ * @returns The exclusively owned {@link BasicChunk} containing the node at `index`. This chunk is part of and owned by `chunks`.
29
+ * @remarks
30
+ * This function may modify the `chunks` array to ensure the node at `index` is in a non-shared {@link BasicChunk}.
31
+ * This can include splitting chunks, and cloning.
32
+ */
33
+ export declare function ensureExclusiveBasicChunk(chunks: TreeChunk[], index: number, compressor: ChunkCompressor): BasicChunk;
11
34
  /**
12
35
  * Implementation of IEditableForest based on copy on write chunks.
13
36
  *
14
37
  * This implementation focuses on performance.
15
38
  */
16
- export declare class ChunkedForest implements IEditableForest {
39
+ export declare class ChunkedForest implements IEditableForest, WithBreakable {
17
40
  #private;
18
41
  roots: BasicChunk;
19
42
  readonly schema: TreeStoredSchemaSubscription;
20
43
  readonly chunker: IChunker;
21
44
  readonly anchors: AnchorSet;
22
45
  readonly idCompressor?: IIdCompressor | undefined;
46
+ readonly breaker: Breakable;
23
47
  private activeVisitor?;
24
48
  private readonly deltaVisitors;
25
49
  readonly events: Listenable<ForestEvents>;
@@ -29,9 +53,9 @@ export declare class ChunkedForest implements IEditableForest {
29
53
  * @param chunker - Chunking policy. TODO: dispose of this when forest is disposed.
30
54
  * @param anchors - anchorSet used to track location in this forest across changes. Callers of applyDelta must ensure this is updated accordingly.
31
55
  */
32
- constructor(roots: BasicChunk, schema: TreeStoredSchemaSubscription, chunker: IChunker, anchors?: AnchorSet, idCompressor?: IIdCompressor | undefined);
56
+ constructor(roots: BasicChunk, schema: TreeStoredSchemaSubscription, chunker: IChunker, anchors?: AnchorSet, idCompressor?: IIdCompressor | undefined, breaker?: Breakable);
33
57
  get isEmpty(): boolean;
34
- clone(schema: TreeStoredSchemaSubscription, _breaker?: Breakable): ChunkedForest;
58
+ clone(schema: TreeStoredSchemaSubscription, breaker?: Breakable): ChunkedForest;
35
59
  chunkField(cursor: ITreeCursorSynchronous): TreeChunk[];
36
60
  forgetAnchor(anchor: Anchor): void;
37
61
  registerAnnouncedVisitor(visitor: () => AnnouncedVisitor): void;
@@ -59,6 +83,6 @@ declare class Cursor extends BasicChunkCursor implements ITreeSubscriptionCursor
59
83
  /**
60
84
  * Creates an implementation of {@link IEditableForest} with no data or schema.
61
85
  */
62
- export declare function buildChunkedForest(chunker: IChunker, anchors?: AnchorSet, idCompressor?: IIdCompressor): ChunkedForest;
86
+ export declare function buildChunkedForest(chunker: IChunker, anchors?: AnchorSet, idCompressor?: IIdCompressor, breaker?: Breakable): ChunkedForest;
63
87
  export {};
64
88
  //# sourceMappingURL=chunkedForest.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chunkedForest.d.ts","sourceRoot":"","sources":["../../../src/feature-libraries/chunked-forest/chunkedForest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chunkedForest.d.ts","sourceRoot":"","sources":["../../../src/feature-libraries/chunked-forest/chunkedForest.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAElE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAEnE,OAAO,EACN,KAAK,MAAM,EACX,SAAS,EACT,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,4BAA4B,EAG5B,oBAAoB,EACpB,KAAK,4BAA4B,EACjC,KAAK,MAAM,EAOX,KAAK,aAAa,EAClB,KAAK,SAAS,EAEd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAMN,SAAS,EACT,KAAK,aAAa,EAClB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACnF,OAAO,EACN,KAAK,eAAe,EACpB,KAAK,QAAQ,EAKb,MAAM,gBAAgB,CAAC;AAWxB;;;;;GAKG;AACH,wBAAgB,kBAAkB,CACjC,MAAM,EAAE,SAAS,SAAS,EAAE,EAC5B,KAAK,EAAE,MAAM,GACX;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,CAiBtE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CACxC,MAAM,EAAE,SAAS,EAAE,EACnB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,eAAe,GACzB,UAAU,CA6CZ;AAgBD;;;;GAIG;AACH,qBAAa,aAAc,YAAW,eAAe,EAAE,aAAa;;IAc3D,KAAK,EAAE,UAAU;aACR,MAAM,EAAE,4BAA4B;aACpC,OAAO,EAAE,QAAQ;aACjB,OAAO,EAAE,SAAS;aAClB,YAAY,CAAC;aACb,OAAO,EAAE,SAAS;IAlBnC,OAAO,CAAC,aAAa,CAAC,CAAe;IAErC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA0C;IAExE,SAAgB,MAAM,EAAE,UAAU,CAAC,YAAY,CAAC,CAAgB;IAEhE;;;;;OAKG;gBAEK,KAAK,EAAE,UAAU,EACR,MAAM,EAAE,4BAA4B,EACpC,OAAO,EAAE,QAAQ,EACjB,OAAO,GAAE,SAA2B,EACpC,YAAY,CAAC,2BAAe,EAC5B,OAAO,GAAE,SAA0C;IAGpE,IAAW,OAAO,IAAI,OAAO,CAG5B;IAEM,KAAK,CAAC,MAAM,EAAE,4BAA4B,EAAE,OAAO,CAAC,EAAE,SAAS,GAAG,aAAa;IAa/E,UAAU,CAAC,MAAM,EAAE,sBAAsB,GAAG,SAAS,EAAE;IAKvD,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAIlC,wBAAwB,CAAC,OAAO,EAAE,MAAM,gBAAgB,GAAG,IAAI;IAI/D,0BAA0B,CAAC,OAAO,EAAE,MAAM,gBAAgB,GAAG,IAAI;IAIjE,cAAc,IAAI,YAAY;IAwNrC,OAAO,CAAC,2BAA2B,CAAK;IACjC,gBAAgB,IAAI,aAAa;IAUjC,cAAc,IAAI,MAAM;IAkBxB,mBAAmB,CACzB,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,uBAAuB,GACnC,oBAAoB;IAUhB,oBAAoB,CAC1B,WAAW,EAAE,WAAW,EACxB,YAAY,EAAE,uBAAuB,GACnC,oBAAoB;IAmBhB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,uBAAuB,GAAG,IAAI;IAoClF,4BAA4B,IAAI,sBAAsB;CAM7D;AAED,cAAM,MAAO,SAAQ,gBAAiB,YAAW,uBAAuB;aAEtD,MAAM,EAAE,aAAa;IAC9B,KAAK,EAAE,4BAA4B;gBAD1B,MAAM,EAAE,aAAa,EAC9B,KAAK,EAAE,4BAA4B,EAC1C,IAAI,EAAE,SAAS,SAAS,EAAE,EAC1B,YAAY,EAAE,aAAa,EAAE,EAC7B,UAAU,EAAE,MAAM,EAAE,EACpB,iBAAiB,EAAE,MAAM,EAAE,EAC3B,qBAAqB,EAAE,MAAM,EAAE,EAC/B,QAAQ,EAAE,aAAa,EACvB,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,MAAM,EACpB,gBAAgB,EAAE,MAAM,EACxB,YAAY,EAAE,aAAa,GAAG,SAAS;IAgBjC,qBAAqB,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI;IAajC,IAAI,IAAI,MAAM;IAmBvB,gBAAgB,IAAI,WAAW;IAO/B,IAAI,IAAI,IAAI;IAIZ,WAAW,IAAI,MAAM;IAIrB,KAAK,IAAI,IAAI;CAIpB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CACjC,OAAO,EAAE,QAAQ,EACjB,OAAO,CAAC,EAAE,SAAS,EACnB,YAAY,CAAC,EAAE,aAAa,EAC5B,OAAO,CAAC,EAAE,SAAS,GACjB,aAAa,CASf"}
@@ -5,14 +5,92 @@
5
5
  var _ChunkedForest_events;
6
6
  import { __classPrivateFieldGet } from "tslib";
7
7
  import { createEmitter } from "@fluid-internal/client-utils";
8
- import { assert, oob, fail } from "@fluidframework/core-utils/internal";
9
- import { AnchorSet, ITreeSubscriptionCursorState, aboveRootPlaceholder, combineVisitors, detachedFieldAsKey, mapCursorField, rootFieldKey, } from "../../core/index.js";
10
- import { brand, getLast, getOrAddEmptyToMap, hasSome, } from "../../util/index.js";
8
+ import { assert, oob, fail, debugAssert } from "@fluidframework/core-utils/internal";
9
+ import { AnchorSet, ITreeSubscriptionCursorState, aboveRootPlaceholder, combineVisitors, detachedFieldAsKey, makeBreakingVisitor, mapCursorField, rootFieldKey, } from "../../core/index.js";
10
+ import { assertNonNegativeSafeInteger, brand, getLast, getOrAddEmptyToMap, hasSome, Breakable, } from "../../util/index.js";
11
11
  import { BasicChunk, BasicChunkCursor } from "./basicChunk.js";
12
12
  import { basicChunkTree, chunkField, chunkTree, splitFieldAtIndex, } from "./chunkTree.js";
13
13
  function makeRoot() {
14
14
  return new BasicChunk(aboveRootPlaceholder, new Map());
15
15
  }
16
+ /** Returns the number of top-level nodes represented by a field's chunks. */
17
+ function getFieldLength(field) {
18
+ return field.reduce((length, chunk) => length + chunk.topLevelLength, 0);
19
+ }
20
+ /**
21
+ * Locates a top-level node within a field's chunk representation.
22
+ * @param chunks - The chunks representing the field.
23
+ * @param index - The node index within the field.
24
+ * @returns The containing chunk, its array index, and the node's offset within it.
25
+ */
26
+ export function locateNodeInChunks(chunks, index) {
27
+ assertNonNegativeSafeInteger(index);
28
+ // Remaining node offset while scanning chunks; afterward, the offset within the matched chunk.
29
+ let indexWithinChunk = index;
30
+ // Array index of the chunk currently being examined.
31
+ let indexOfChunk = 0;
32
+ while (true) {
33
+ const chunk = chunks[indexOfChunk] ?? oob();
34
+ if (indexWithinChunk < chunk.topLevelLength) {
35
+ return { chunk, indexOfChunk, indexWithinChunk };
36
+ }
37
+ indexWithinChunk -= chunk.topLevelLength;
38
+ indexOfChunk++;
39
+ if (indexOfChunk === chunks.length) {
40
+ fail(0xaf7 /* missing edited node */);
41
+ }
42
+ }
43
+ }
44
+ /**
45
+ * Ensures the node at index `index` within the field represented by `chunks` is contained in a non-shared {@link BasicChunk}.
46
+ *
47
+ * @param chunks - The chunks representing the field which will be modified to ensure the node at
48
+ * `index` is in a non-shared {@link BasicChunk}.
49
+ * @param index - The node index within the field.
50
+ * @returns The exclusively owned {@link BasicChunk} containing the node at `index`. This chunk is part of and owned by `chunks`.
51
+ * @remarks
52
+ * This function may modify the `chunks` array to ensure the node at `index` is in a non-shared {@link BasicChunk}.
53
+ * This can include splitting chunks, and cloning.
54
+ */
55
+ export function ensureExclusiveBasicChunk(chunks, index, compressor) {
56
+ const { chunk, indexOfChunk, indexWithinChunk } = locateNodeInChunks(chunks, index);
57
+ // Normalize to a BasicChunk, splitting the chunk if needed.
58
+ let finalIndexOfChunk;
59
+ let basicChunk;
60
+ if (chunk instanceof BasicChunk) {
61
+ basicChunk = chunk;
62
+ finalIndexOfChunk = indexOfChunk;
63
+ }
64
+ else {
65
+ // TODO:Perf: support in place editing of other chunk formats when possible:
66
+ // 1. Support updating values in uniform chunks.
67
+ // 2. Support traversing sequence chunks.
68
+ //
69
+ // Maybe build path when visitor navigates then lazily sync to chunk tree when editing?
70
+ const newChunks = mapCursorField(chunk.cursor(), (cursor) => basicChunkTree(cursor, compressor));
71
+ // TODO: this could fail for really long chunks being split (due to argument count limits).
72
+ // Current implementations of chunks shouldn't ever be that long, but it could be an issue if they get bigger.
73
+ chunks.splice(indexOfChunk, 1, ...newChunks);
74
+ // We just overwrote the reference to the old chunk in the array, so drop the ref count for it.
75
+ chunk.referenceRemoved();
76
+ // Sanity check that the chunk indexing is as expected before updating it.
77
+ debugAssert(() => newChunks[indexWithinChunk] === chunks[indexOfChunk + indexWithinChunk] ||
78
+ "bad chunk indexing");
79
+ basicChunk = newChunks[indexWithinChunk] ?? oob();
80
+ finalIndexOfChunk = indexOfChunk + indexWithinChunk;
81
+ }
82
+ debugAssert(() => chunks[finalIndexOfChunk] === basicChunk || "bad child index");
83
+ // Ensure the BasicChunk we have is exclusively owned, so we can edit it in place.
84
+ let exclusiveChunk;
85
+ if (basicChunk.isShared()) {
86
+ exclusiveChunk = chunks[finalIndexOfChunk] = basicChunk.clone();
87
+ basicChunk.referenceRemoved();
88
+ }
89
+ else {
90
+ exclusiveChunk = basicChunk;
91
+ }
92
+ return exclusiveChunk;
93
+ }
16
94
  /**
17
95
  * Implementation of IEditableForest based on copy on write chunks.
18
96
  *
@@ -25,25 +103,29 @@ export class ChunkedForest {
25
103
  * @param chunker - Chunking policy. TODO: dispose of this when forest is disposed.
26
104
  * @param anchors - anchorSet used to track location in this forest across changes. Callers of applyDelta must ensure this is updated accordingly.
27
105
  */
28
- constructor(roots, schema, chunker, anchors = new AnchorSet(), idCompressor) {
106
+ constructor(roots, schema, chunker, anchors = new AnchorSet(), idCompressor, breaker = new Breakable("ChunkedForest")) {
29
107
  this.roots = roots;
30
108
  this.schema = schema;
31
109
  this.chunker = chunker;
32
110
  this.anchors = anchors;
33
111
  this.idCompressor = idCompressor;
112
+ this.breaker = breaker;
34
113
  this.deltaVisitors = new Set();
35
114
  _ChunkedForest_events.set(this, createEmitter());
36
115
  this.events = __classPrivateFieldGet(this, _ChunkedForest_events, "f");
37
116
  this.nextDetachedFieldIdentifier = 0;
38
117
  }
39
118
  get isEmpty() {
119
+ this.breaker.use();
40
120
  return this.roots.fields.size === 0;
41
121
  }
42
- clone(schema, _breaker) {
122
+ clone(schema, breaker) {
123
+ this.breaker.use();
43
124
  this.roots.referenceAdded();
44
- return new ChunkedForest(this.roots, schema, this.chunker.clone(schema));
125
+ return new ChunkedForest(this.roots, schema, this.chunker.clone(schema), undefined, this.idCompressor, breaker ?? this.breaker);
45
126
  }
46
127
  chunkField(cursor) {
128
+ this.breaker.use();
47
129
  return chunkField(cursor, { idCompressor: this.idCompressor, policy: this.chunker });
48
130
  }
49
131
  forgetAnchor(anchor) {
@@ -56,15 +138,29 @@ export class ChunkedForest {
56
138
  this.deltaVisitors.delete(visitor);
57
139
  }
58
140
  acquireVisitor() {
141
+ this.breaker.use();
59
142
  assert(this.activeVisitor === undefined, 0x76a /* Must release existing visitor before acquiring another */);
60
143
  if (this.roots.isShared()) {
61
144
  this.roots = this.roots.clone();
62
145
  }
146
+ // The `CombinableVisitor` which can apply deltas to this forest.
147
+ // Annoyingly declaring the type here or in a satisfies clause causes this code not to build,
148
+ // so the type is inferred.
149
+ //
150
+ // This visitor works by shallow copying (where needed) the forest as it's walked down
151
+ // to ensure the location being traversed (and thus possibly edited) is an exclusively owned BasicChunk.
152
+ // Future optimizations may improve this, but currently that is a requirement for the editing code to work.
63
153
  const forestVisitor = {
64
154
  forest: this,
65
- // Current location in the tree, as a non-shared BasicChunk (TODO: support in-place modification of other chunk formats when possible).
66
- // Start above root detached sequences.
155
+ /**
156
+ * Current location in the tree, as a non-shared BasicChunk (TODO: support in-place modification of other chunk formats when possible).
157
+ * Starts above root detached sequences.
158
+ */
67
159
  mutableChunkStack: [],
160
+ /**
161
+ * When at a node level, this is set to the basic chunk for the current node.
162
+ * When at a field level, undefined, see mutableChunkStack for the field.
163
+ */
68
164
  mutableChunk: this.roots,
69
165
  getParent() {
70
166
  assert(hasSome(this.mutableChunkStack), 0x532 /* invalid access to root's parent */);
@@ -78,10 +174,17 @@ export class ChunkedForest {
78
174
  },
79
175
  destroy(detachedField, count) {
80
176
  __classPrivateFieldGet(this.forest, _ChunkedForest_events, "f").emit("beforeChange");
177
+ const field = this.forest.roots.fields.get(detachedField);
178
+ assert(field !== undefined, 0xd1d /* Destroyed field must exist */);
179
+ assert(getFieldLength(field) === count, 0xd1e /* Destroy count must match field length */);
81
180
  this.forest.roots.fields.delete(detachedField);
181
+ for (const chunk of field) {
182
+ chunk.referenceRemoved();
183
+ }
82
184
  },
83
185
  create(content, destination) {
84
186
  __classPrivateFieldGet(this.forest, _ChunkedForest_events, "f").emit("beforeChange");
187
+ assert(!this.forest.roots.fields.has(destination), 0xd1f /* Create destination must be a new empty field */);
85
188
  const chunks = content.map((c) => chunkTree(c, {
86
189
  policy: this.forest.chunker,
87
190
  idCompressor: this.forest.idCompressor,
@@ -103,17 +206,18 @@ export class ChunkedForest {
103
206
  */
104
207
  attachEdit(source, count, destination) {
105
208
  __classPrivateFieldGet(this.forest, _ChunkedForest_events, "f").emit("beforeChange");
106
- const sourceField = this.forest.roots.fields.get(source) ?? [];
107
- this.forest.roots.fields.delete(source);
108
- if (sourceField.length === 0) {
109
- return; // Prevent creating 0 sized fields when inserting empty into empty.
110
- }
111
209
  const parent = this.getParent();
210
+ assert(parent.mutableChunk !== this.forest.roots || parent.key !== source, 0xd20 /* Attach source field must be different from current field */);
211
+ const sourceField = this.forest.roots.fields.get(source);
212
+ assert(sourceField !== undefined, 0xd21 /* Attach source field must exist */);
213
+ assert(getFieldLength(sourceField) === count, 0xd22 /* Attach must consume all nodes in source field */);
112
214
  const destinationField = getOrAddEmptyToMap(parent.mutableChunk.fields, parent.key);
215
+ assert(destination <= getFieldLength(destinationField), 0xd23 /* Attach destination must not exceed field length */);
113
216
  const destinationChunkIndex = splitFieldAtIndex(destinationField, destination, {
114
217
  policy: this.forest.chunker,
115
218
  idCompressor: this.forest.idCompressor,
116
219
  });
220
+ this.forest.roots.fields.delete(source);
117
221
  // TODO: this will fail for very large moves due to argument limits.
118
222
  destinationField.splice(destinationChunkIndex, 0, ...sourceField);
119
223
  },
@@ -133,7 +237,12 @@ export class ChunkedForest {
133
237
  __classPrivateFieldGet(this.forest, _ChunkedForest_events, "f").emit("beforeChange");
134
238
  const parent = this.getParent();
135
239
  const sourceField = parent.mutableChunk.fields.get(parent.key) ?? [];
136
- assert(source.start <= source.end, 0xcf8 /* detach range start must not exceed end */);
240
+ assert(source.start <= source.end, 0xd24 /* Detach range start must not exceed end */);
241
+ assert(source.end <= getFieldLength(sourceField), 0xd25 /* Detach range must not exceed field length */);
242
+ if (destination !== undefined) {
243
+ assert(parent.mutableChunk !== this.forest.roots || parent.key !== destination, 0xd26 /* Detach destination field must be different from current field */);
244
+ assert(!this.forest.roots.fields.has(destination), 0xd27 /* Detach destination must be a new empty field */);
245
+ }
137
246
  const policy = {
138
247
  policy: this.forest.chunker,
139
248
  idCompressor: this.forest.idCompressor,
@@ -151,7 +260,6 @@ export class ChunkedForest {
151
260
  }
152
261
  }
153
262
  else {
154
- assert(!this.forest.roots.fields.has(destination), 0x7af /* Destination must be a new empty detached field */);
155
263
  if (newField.length > 0) {
156
264
  this.forest.roots.fields.set(destination, newField);
157
265
  }
@@ -162,46 +270,20 @@ export class ChunkedForest {
162
270
  parent.mutableChunk.fields.delete(parent.key);
163
271
  }
164
272
  },
273
+ /**
274
+ * Ensure the selected node (by `index`) is an exclusively owned basic node,
275
+ * and store it under `this.mutableChunk`.
276
+ */
165
277
  enterNode(index) {
166
278
  assert(this.mutableChunk === undefined, 0x535 /* should be in field */);
279
+ // Get the mutable parent, which we might have to modify to ensure the desired child is an exclusively owned (and thus mutable) BasicChunk.
167
280
  const parent = this.getParent();
281
+ // Lookup the current location of the node to be entered
168
282
  const chunks = parent.mutableChunk.fields.get(parent.key) ?? fail(0xaf6 /* missing edited field */);
169
- let indexWithinChunk = index;
170
- let indexOfChunk = 0;
171
- let chunk = chunks[indexOfChunk] ?? oob();
172
- while (indexWithinChunk >= chunk.topLevelLength) {
173
- indexWithinChunk -= chunk.topLevelLength;
174
- indexOfChunk++;
175
- if (indexOfChunk === chunks.length) {
176
- fail(0xaf7 /* missing edited node */);
177
- }
178
- chunk = chunks[indexOfChunk] ?? oob();
179
- }
180
- let found = chunks[indexOfChunk] ?? oob();
181
- if (!(found instanceof BasicChunk)) {
182
- // TODO:Perf: support in place editing of other chunk formats when possible:
183
- // 1. Support updating values in uniform chunks.
184
- // 2. Support traversing sequence chunks.
185
- //
186
- // Maybe build path when visitor navigates then lazily sync to chunk tree when editing?
187
- const newChunks = mapCursorField(found.cursor(), (cursor) => basicChunkTree(cursor, {
188
- policy: this.forest.chunker,
189
- idCompressor: this.forest.idCompressor,
190
- }));
191
- // TODO: this could fail for really long chunks being split (due to argument count limits).
192
- // Current implementations of chunks shouldn't ever be that long, but it could be an issue if they get bigger.
193
- chunks.splice(indexOfChunk, 1, ...newChunks);
194
- found.referenceRemoved();
195
- found = newChunks[indexWithinChunk] ?? oob();
196
- }
197
- assert(found instanceof BasicChunk, 0x536 /* chunk should have been normalized */);
198
- if (found.isShared()) {
199
- this.mutableChunk = chunks[indexOfChunk] = found.clone();
200
- found.referenceRemoved();
201
- }
202
- else {
203
- this.mutableChunk = found;
204
- }
283
+ this.mutableChunk = ensureExclusiveBasicChunk(chunks, index, {
284
+ policy: this.forest.chunker,
285
+ idCompressor: this.forest.idCompressor,
286
+ });
205
287
  },
206
288
  exitNode(index) {
207
289
  assert(this.mutableChunk !== undefined, 0x537 /* should be in node */);
@@ -222,9 +304,12 @@ export class ChunkedForest {
222
304
  for (const getVisitor of this.deltaVisitors) {
223
305
  announcedVisitors.push(getVisitor());
224
306
  }
225
- const combinedVisitor = combineVisitors([forestVisitor, ...announcedVisitors]);
226
- this.activeVisitor = combinedVisitor;
227
- return combinedVisitor;
307
+ const visitor = combineVisitors([
308
+ makeBreakingVisitor(forestVisitor, this.breaker),
309
+ ...announcedVisitors,
310
+ ]);
311
+ this.activeVisitor = visitor;
312
+ return visitor;
228
313
  }
229
314
  newDetachedField() {
230
315
  const field = brand(String(this.nextDetachedFieldIdentifier));
@@ -233,9 +318,11 @@ export class ChunkedForest {
233
318
  return field;
234
319
  }
235
320
  allocateCursor() {
321
+ this.breaker.use();
236
322
  return new Cursor(this, ITreeSubscriptionCursorState.Cleared, [], [], [], [], [], [], 0, 0, 0, undefined);
237
323
  }
238
324
  tryMoveCursorToNode(destination, cursorToMove) {
325
+ this.breaker.use();
239
326
  const path = this.anchors.locate(destination);
240
327
  if (path === undefined) {
241
328
  return -1 /* TreeNavigationResult.NotFound */;
@@ -244,6 +331,7 @@ export class ChunkedForest {
244
331
  return 1 /* TreeNavigationResult.Ok */;
245
332
  }
246
333
  tryMoveCursorToField(destination, cursorToMove) {
334
+ this.breaker.use();
247
335
  assert(cursorToMove instanceof Cursor, 0x53b /* ChunkedForest must only be given its own Cursor type */);
248
336
  if (destination.parent === undefined) {
249
337
  cursorToMove.setToDetachedSequence(destination.fieldKey);
@@ -257,6 +345,7 @@ export class ChunkedForest {
257
345
  return 1 /* TreeNavigationResult.Ok */;
258
346
  }
259
347
  moveCursorToPath(destination, cursorToMove) {
348
+ this.breaker.use();
260
349
  assert(cursorToMove instanceof Cursor, 0x53c /* ChunkedForest must only be given its own Cursor type */);
261
350
  assert(cursorToMove.forest === this, 0x53d /* ChunkedForest must only be given its own Cursor */);
262
351
  const indexStack = [];
@@ -283,6 +372,7 @@ export class ChunkedForest {
283
372
  }
284
373
  }
285
374
  getCursorAboveDetachedFields() {
375
+ this.breaker.use();
286
376
  const rootCursor = this.roots.cursor();
287
377
  rootCursor.enterNode(0);
288
378
  return rootCursor;
@@ -331,7 +421,7 @@ class Cursor extends BasicChunkCursor {
331
421
  /**
332
422
  * Creates an implementation of {@link IEditableForest} with no data or schema.
333
423
  */
334
- export function buildChunkedForest(chunker, anchors, idCompressor) {
335
- return new ChunkedForest(makeRoot(), chunker.schema, chunker, anchors, idCompressor);
424
+ export function buildChunkedForest(chunker, anchors, idCompressor, breaker) {
425
+ return new ChunkedForest(makeRoot(), chunker.schema, chunker, anchors, idCompressor, breaker);
336
426
  }
337
427
  //# sourceMappingURL=chunkedForest.js.map