@fluidframework/tree 2.10.0 → 2.11.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 (465) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/api-report/tree.alpha.api.md +47 -16
  3. package/api-report/tree.beta.api.md +5 -14
  4. package/api-report/tree.legacy.alpha.api.md +5 -14
  5. package/api-report/tree.legacy.public.api.md +5 -14
  6. package/api-report/tree.public.api.md +5 -14
  7. package/dist/alpha.d.ts +9 -0
  8. package/dist/core/forest/forest.d.ts +10 -2
  9. package/dist/core/forest/forest.d.ts.map +1 -1
  10. package/dist/core/forest/forest.js.map +1 -1
  11. package/dist/core/index.d.ts +2 -2
  12. package/dist/core/index.d.ts.map +1 -1
  13. package/dist/core/index.js +3 -2
  14. package/dist/core/index.js.map +1 -1
  15. package/dist/core/rebase/utils.d.ts +1 -1
  16. package/dist/core/rebase/utils.d.ts.map +1 -1
  17. package/dist/core/rebase/utils.js +11 -8
  18. package/dist/core/rebase/utils.js.map +1 -1
  19. package/dist/core/revertible.d.ts +30 -1
  20. package/dist/core/revertible.d.ts.map +1 -1
  21. package/dist/core/revertible.js.map +1 -1
  22. package/dist/core/schema-stored/storedSchemaRepository.d.ts +2 -2
  23. package/dist/core/schema-stored/storedSchemaRepository.d.ts.map +1 -1
  24. package/dist/core/schema-stored/storedSchemaRepository.js +5 -5
  25. package/dist/core/schema-stored/storedSchemaRepository.js.map +1 -1
  26. package/dist/core/tree/anchorSet.d.ts +2 -2
  27. package/dist/core/tree/anchorSet.d.ts.map +1 -1
  28. package/dist/core/tree/anchorSet.js +21 -21
  29. package/dist/core/tree/anchorSet.js.map +1 -1
  30. package/dist/core/tree/detachedFieldIndexCodec.d.ts.map +1 -1
  31. package/dist/core/tree/detachedFieldIndexCodec.js +3 -2
  32. package/dist/core/tree/detachedFieldIndexCodec.js.map +1 -1
  33. package/dist/core/tree/index.d.ts +1 -1
  34. package/dist/core/tree/index.d.ts.map +1 -1
  35. package/dist/core/tree/index.js +2 -1
  36. package/dist/core/tree/index.js.map +1 -1
  37. package/dist/core/tree/visitorUtils.d.ts +25 -1
  38. package/dist/core/tree/visitorUtils.d.ts.map +1 -1
  39. package/dist/core/tree/visitorUtils.js +29 -1
  40. package/dist/core/tree/visitorUtils.js.map +1 -1
  41. package/dist/feature-libraries/chunked-forest/chunkedForest.d.ts +5 -2
  42. package/dist/feature-libraries/chunked-forest/chunkedForest.d.ts.map +1 -1
  43. package/dist/feature-libraries/chunked-forest/chunkedForest.js +24 -14
  44. package/dist/feature-libraries/chunked-forest/chunkedForest.js.map +1 -1
  45. package/dist/feature-libraries/chunked-forest/uniformChunk.d.ts.map +1 -1
  46. package/dist/feature-libraries/chunked-forest/uniformChunk.js +2 -2
  47. package/dist/feature-libraries/chunked-forest/uniformChunk.js.map +1 -1
  48. package/dist/feature-libraries/flex-tree/context.d.ts +1 -1
  49. package/dist/feature-libraries/flex-tree/context.d.ts.map +1 -1
  50. package/dist/feature-libraries/flex-tree/context.js.map +1 -1
  51. package/dist/feature-libraries/index.d.ts +1 -0
  52. package/dist/feature-libraries/index.d.ts.map +1 -1
  53. package/dist/feature-libraries/index.js +4 -1
  54. package/dist/feature-libraries/index.js.map +1 -1
  55. package/dist/feature-libraries/indexing/anchorTreeIndex.d.ts +132 -0
  56. package/dist/feature-libraries/indexing/anchorTreeIndex.d.ts.map +1 -0
  57. package/dist/feature-libraries/indexing/anchorTreeIndex.js +361 -0
  58. package/dist/feature-libraries/indexing/anchorTreeIndex.js.map +1 -0
  59. package/dist/feature-libraries/indexing/index.d.ts +7 -0
  60. package/dist/feature-libraries/indexing/index.d.ts.map +1 -0
  61. package/dist/feature-libraries/indexing/index.js +11 -0
  62. package/dist/feature-libraries/indexing/index.js.map +1 -0
  63. package/dist/feature-libraries/indexing/types.d.ts +32 -0
  64. package/dist/feature-libraries/indexing/types.d.ts.map +1 -0
  65. package/dist/{events/interop.js → feature-libraries/indexing/types.js} +1 -1
  66. package/dist/feature-libraries/indexing/types.js.map +1 -0
  67. package/dist/feature-libraries/object-forest/objectForest.d.ts +5 -2
  68. package/dist/feature-libraries/object-forest/objectForest.d.ts.map +1 -1
  69. package/dist/feature-libraries/object-forest/objectForest.js +21 -11
  70. package/dist/feature-libraries/object-forest/objectForest.js.map +1 -1
  71. package/dist/feature-libraries/sequence-field/invert.d.ts.map +1 -1
  72. package/dist/feature-libraries/sequence-field/invert.js +2 -2
  73. package/dist/feature-libraries/sequence-field/invert.js.map +1 -1
  74. package/dist/feature-libraries/sequence-field/sequenceFieldToDelta.js +3 -2
  75. package/dist/feature-libraries/sequence-field/sequenceFieldToDelta.js.map +1 -1
  76. package/dist/index.d.ts +4 -4
  77. package/dist/index.d.ts.map +1 -1
  78. package/dist/index.js +4 -1
  79. package/dist/index.js.map +1 -1
  80. package/dist/packageVersion.d.ts +1 -1
  81. package/dist/packageVersion.js +1 -1
  82. package/dist/packageVersion.js.map +1 -1
  83. package/dist/shared-tree/index.d.ts +1 -1
  84. package/dist/shared-tree/index.d.ts.map +1 -1
  85. package/dist/shared-tree/index.js +1 -2
  86. package/dist/shared-tree/index.js.map +1 -1
  87. package/dist/shared-tree/schematizingTreeView.d.ts +7 -1
  88. package/dist/shared-tree/schematizingTreeView.d.ts.map +1 -1
  89. package/dist/shared-tree/schematizingTreeView.js +31 -30
  90. package/dist/shared-tree/schematizingTreeView.js.map +1 -1
  91. package/dist/shared-tree/sharedTree.d.ts +3 -0
  92. package/dist/shared-tree/sharedTree.d.ts.map +1 -1
  93. package/dist/shared-tree/sharedTree.js +56 -20
  94. package/dist/shared-tree/sharedTree.js.map +1 -1
  95. package/dist/shared-tree/sharedTreeChangeFamily.d.ts.map +1 -1
  96. package/dist/shared-tree/sharedTreeChangeFamily.js +3 -3
  97. package/dist/shared-tree/sharedTreeChangeFamily.js.map +1 -1
  98. package/dist/shared-tree/treeCheckout.d.ts +28 -64
  99. package/dist/shared-tree/treeCheckout.d.ts.map +1 -1
  100. package/dist/shared-tree/treeCheckout.js +152 -129
  101. package/dist/shared-tree/treeCheckout.js.map +1 -1
  102. package/dist/shared-tree-core/branch.d.ts +25 -81
  103. package/dist/shared-tree-core/branch.d.ts.map +1 -1
  104. package/dist/shared-tree-core/branch.js +72 -151
  105. package/dist/shared-tree-core/branch.js.map +1 -1
  106. package/dist/shared-tree-core/branchCommitEnricher.d.ts +19 -33
  107. package/dist/shared-tree-core/branchCommitEnricher.d.ts.map +1 -1
  108. package/dist/shared-tree-core/branchCommitEnricher.js +73 -54
  109. package/dist/shared-tree-core/branchCommitEnricher.js.map +1 -1
  110. package/dist/shared-tree-core/defaultResubmitMachine.d.ts.map +1 -1
  111. package/dist/shared-tree-core/defaultResubmitMachine.js +2 -1
  112. package/dist/shared-tree-core/defaultResubmitMachine.js.map +1 -1
  113. package/dist/shared-tree-core/editManager.d.ts.map +1 -1
  114. package/dist/shared-tree-core/editManager.js +2 -2
  115. package/dist/shared-tree-core/editManager.js.map +1 -1
  116. package/dist/shared-tree-core/index.d.ts +1 -1
  117. package/dist/shared-tree-core/index.d.ts.map +1 -1
  118. package/dist/shared-tree-core/index.js +4 -3
  119. package/dist/shared-tree-core/index.js.map +1 -1
  120. package/dist/shared-tree-core/sharedTreeCore.d.ts +2 -2
  121. package/dist/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
  122. package/dist/shared-tree-core/sharedTreeCore.js +11 -52
  123. package/dist/shared-tree-core/sharedTreeCore.js.map +1 -1
  124. package/dist/shared-tree-core/transaction.d.ts +108 -0
  125. package/dist/shared-tree-core/transaction.d.ts.map +1 -0
  126. package/dist/shared-tree-core/transaction.js +99 -0
  127. package/dist/shared-tree-core/transaction.js.map +1 -0
  128. package/dist/shared-tree-core/transactionEnricher.d.ts +8 -13
  129. package/dist/shared-tree-core/transactionEnricher.d.ts.map +1 -1
  130. package/dist/shared-tree-core/transactionEnricher.js +41 -21
  131. package/dist/shared-tree-core/transactionEnricher.js.map +1 -1
  132. package/dist/simple-tree/api/identifierIndex.d.ts +21 -0
  133. package/dist/simple-tree/api/identifierIndex.d.ts.map +1 -0
  134. package/dist/simple-tree/api/identifierIndex.js +45 -0
  135. package/dist/simple-tree/api/identifierIndex.js.map +1 -0
  136. package/dist/simple-tree/api/index.d.ts +2 -0
  137. package/dist/simple-tree/api/index.d.ts.map +1 -1
  138. package/dist/simple-tree/api/index.js +5 -1
  139. package/dist/simple-tree/api/index.js.map +1 -1
  140. package/dist/simple-tree/api/simpleSchemaToJsonSchema.js +9 -7
  141. package/dist/simple-tree/api/simpleSchemaToJsonSchema.js.map +1 -1
  142. package/dist/simple-tree/api/simpleTreeIndex.d.ts +65 -0
  143. package/dist/simple-tree/api/simpleTreeIndex.d.ts.map +1 -0
  144. package/dist/simple-tree/api/simpleTreeIndex.js +91 -0
  145. package/dist/simple-tree/api/simpleTreeIndex.js.map +1 -0
  146. package/dist/simple-tree/api/tree.d.ts +4 -5
  147. package/dist/simple-tree/api/tree.d.ts.map +1 -1
  148. package/dist/simple-tree/api/tree.js.map +1 -1
  149. package/dist/simple-tree/api/treeNodeApi.js.map +1 -1
  150. package/dist/simple-tree/core/index.d.ts +1 -1
  151. package/dist/simple-tree/core/index.d.ts.map +1 -1
  152. package/dist/simple-tree/core/index.js +2 -1
  153. package/dist/simple-tree/core/index.js.map +1 -1
  154. package/dist/simple-tree/core/treeNodeKernel.d.ts +6 -2
  155. package/dist/simple-tree/core/treeNodeKernel.d.ts.map +1 -1
  156. package/dist/simple-tree/core/treeNodeKernel.js +53 -22
  157. package/dist/simple-tree/core/treeNodeKernel.js.map +1 -1
  158. package/dist/simple-tree/core/unhydratedFlexTree.d.ts +1 -1
  159. package/dist/simple-tree/core/unhydratedFlexTree.d.ts.map +1 -1
  160. package/dist/simple-tree/core/unhydratedFlexTree.js +2 -2
  161. package/dist/simple-tree/core/unhydratedFlexTree.js.map +1 -1
  162. package/dist/simple-tree/index.d.ts +1 -1
  163. package/dist/simple-tree/index.d.ts.map +1 -1
  164. package/dist/simple-tree/index.js +4 -2
  165. package/dist/simple-tree/index.js.map +1 -1
  166. package/dist/simple-tree/objectNode.d.ts +7 -2
  167. package/dist/simple-tree/objectNode.d.ts.map +1 -1
  168. package/dist/simple-tree/objectNode.js.map +1 -1
  169. package/dist/simple-tree/toMapTree.js +3 -3
  170. package/dist/simple-tree/toMapTree.js.map +1 -1
  171. package/dist/util/index.d.ts +1 -2
  172. package/dist/util/index.d.ts.map +1 -1
  173. package/dist/util/index.js +5 -4
  174. package/dist/util/index.js.map +1 -1
  175. package/dist/util/typeCheck.d.ts +6 -1
  176. package/dist/util/typeCheck.d.ts.map +1 -1
  177. package/dist/util/typeCheck.js.map +1 -1
  178. package/dist/util/typeCheckTests.d.ts +14 -2
  179. package/dist/util/typeCheckTests.d.ts.map +1 -1
  180. package/dist/util/typeCheckTests.js.map +1 -1
  181. package/dist/util/utils.d.ts +29 -0
  182. package/dist/util/utils.d.ts.map +1 -1
  183. package/dist/util/utils.js +13 -1
  184. package/dist/util/utils.js.map +1 -1
  185. package/lib/alpha.d.ts +9 -0
  186. package/lib/core/forest/forest.d.ts +10 -2
  187. package/lib/core/forest/forest.d.ts.map +1 -1
  188. package/lib/core/forest/forest.js.map +1 -1
  189. package/lib/core/index.d.ts +2 -2
  190. package/lib/core/index.d.ts.map +1 -1
  191. package/lib/core/index.js +2 -2
  192. package/lib/core/index.js.map +1 -1
  193. package/lib/core/rebase/utils.d.ts +1 -1
  194. package/lib/core/rebase/utils.d.ts.map +1 -1
  195. package/lib/core/rebase/utils.js +11 -8
  196. package/lib/core/rebase/utils.js.map +1 -1
  197. package/lib/core/revertible.d.ts +30 -1
  198. package/lib/core/revertible.d.ts.map +1 -1
  199. package/lib/core/revertible.js.map +1 -1
  200. package/lib/core/schema-stored/storedSchemaRepository.d.ts +2 -2
  201. package/lib/core/schema-stored/storedSchemaRepository.d.ts.map +1 -1
  202. package/lib/core/schema-stored/storedSchemaRepository.js +1 -1
  203. package/lib/core/schema-stored/storedSchemaRepository.js.map +1 -1
  204. package/lib/core/tree/anchorSet.d.ts +2 -2
  205. package/lib/core/tree/anchorSet.d.ts.map +1 -1
  206. package/lib/core/tree/anchorSet.js +1 -1
  207. package/lib/core/tree/anchorSet.js.map +1 -1
  208. package/lib/core/tree/detachedFieldIndexCodec.d.ts.map +1 -1
  209. package/lib/core/tree/detachedFieldIndexCodec.js +4 -3
  210. package/lib/core/tree/detachedFieldIndexCodec.js.map +1 -1
  211. package/lib/core/tree/index.d.ts +1 -1
  212. package/lib/core/tree/index.d.ts.map +1 -1
  213. package/lib/core/tree/index.js +1 -1
  214. package/lib/core/tree/index.js.map +1 -1
  215. package/lib/core/tree/visitorUtils.d.ts +25 -1
  216. package/lib/core/tree/visitorUtils.d.ts.map +1 -1
  217. package/lib/core/tree/visitorUtils.js +27 -0
  218. package/lib/core/tree/visitorUtils.js.map +1 -1
  219. package/lib/feature-libraries/chunked-forest/chunkedForest.d.ts +5 -2
  220. package/lib/feature-libraries/chunked-forest/chunkedForest.d.ts.map +1 -1
  221. package/lib/feature-libraries/chunked-forest/chunkedForest.js +18 -8
  222. package/lib/feature-libraries/chunked-forest/chunkedForest.js.map +1 -1
  223. package/lib/feature-libraries/chunked-forest/uniformChunk.d.ts.map +1 -1
  224. package/lib/feature-libraries/chunked-forest/uniformChunk.js +3 -3
  225. package/lib/feature-libraries/chunked-forest/uniformChunk.js.map +1 -1
  226. package/lib/feature-libraries/flex-tree/context.d.ts +1 -1
  227. package/lib/feature-libraries/flex-tree/context.d.ts.map +1 -1
  228. package/lib/feature-libraries/flex-tree/context.js.map +1 -1
  229. package/lib/feature-libraries/index.d.ts +1 -0
  230. package/lib/feature-libraries/index.d.ts.map +1 -1
  231. package/lib/feature-libraries/index.js +1 -0
  232. package/lib/feature-libraries/index.js.map +1 -1
  233. package/lib/feature-libraries/indexing/anchorTreeIndex.d.ts +132 -0
  234. package/lib/feature-libraries/indexing/anchorTreeIndex.d.ts.map +1 -0
  235. package/lib/feature-libraries/indexing/anchorTreeIndex.js +356 -0
  236. package/lib/feature-libraries/indexing/anchorTreeIndex.js.map +1 -0
  237. package/lib/feature-libraries/indexing/index.d.ts +7 -0
  238. package/lib/feature-libraries/indexing/index.d.ts.map +1 -0
  239. package/lib/{events → feature-libraries/indexing}/index.js +1 -1
  240. package/lib/feature-libraries/indexing/index.js.map +1 -0
  241. package/lib/feature-libraries/indexing/types.d.ts +32 -0
  242. package/lib/feature-libraries/indexing/types.d.ts.map +1 -0
  243. package/lib/{events/interop.js → feature-libraries/indexing/types.js} +1 -1
  244. package/lib/feature-libraries/indexing/types.js.map +1 -0
  245. package/lib/feature-libraries/object-forest/objectForest.d.ts +5 -2
  246. package/lib/feature-libraries/object-forest/objectForest.d.ts.map +1 -1
  247. package/lib/feature-libraries/object-forest/objectForest.js +15 -5
  248. package/lib/feature-libraries/object-forest/objectForest.js.map +1 -1
  249. package/lib/feature-libraries/sequence-field/invert.d.ts.map +1 -1
  250. package/lib/feature-libraries/sequence-field/invert.js +4 -4
  251. package/lib/feature-libraries/sequence-field/invert.js.map +1 -1
  252. package/lib/feature-libraries/sequence-field/sequenceFieldToDelta.js +4 -3
  253. package/lib/feature-libraries/sequence-field/sequenceFieldToDelta.js.map +1 -1
  254. package/lib/index.d.ts +4 -4
  255. package/lib/index.d.ts.map +1 -1
  256. package/lib/index.js +1 -1
  257. package/lib/index.js.map +1 -1
  258. package/lib/packageVersion.d.ts +1 -1
  259. package/lib/packageVersion.js +1 -1
  260. package/lib/packageVersion.js.map +1 -1
  261. package/lib/shared-tree/index.d.ts +1 -1
  262. package/lib/shared-tree/index.d.ts.map +1 -1
  263. package/lib/shared-tree/index.js +1 -1
  264. package/lib/shared-tree/index.js.map +1 -1
  265. package/lib/shared-tree/schematizingTreeView.d.ts +7 -1
  266. package/lib/shared-tree/schematizingTreeView.d.ts.map +1 -1
  267. package/lib/shared-tree/schematizingTreeView.js +2 -2
  268. package/lib/shared-tree/schematizingTreeView.js.map +1 -1
  269. package/lib/shared-tree/sharedTree.d.ts +3 -0
  270. package/lib/shared-tree/sharedTree.d.ts.map +1 -1
  271. package/lib/shared-tree/sharedTree.js +37 -1
  272. package/lib/shared-tree/sharedTree.js.map +1 -1
  273. package/lib/shared-tree/sharedTreeChangeFamily.d.ts.map +1 -1
  274. package/lib/shared-tree/sharedTreeChangeFamily.js +5 -5
  275. package/lib/shared-tree/sharedTreeChangeFamily.js.map +1 -1
  276. package/lib/shared-tree/treeCheckout.d.ts +28 -64
  277. package/lib/shared-tree/treeCheckout.d.ts.map +1 -1
  278. package/lib/shared-tree/treeCheckout.js +140 -116
  279. package/lib/shared-tree/treeCheckout.js.map +1 -1
  280. package/lib/shared-tree-core/branch.d.ts +25 -81
  281. package/lib/shared-tree-core/branch.d.ts.map +1 -1
  282. package/lib/shared-tree-core/branch.js +72 -151
  283. package/lib/shared-tree-core/branch.js.map +1 -1
  284. package/lib/shared-tree-core/branchCommitEnricher.d.ts +19 -33
  285. package/lib/shared-tree-core/branchCommitEnricher.d.ts.map +1 -1
  286. package/lib/shared-tree-core/branchCommitEnricher.js +74 -55
  287. package/lib/shared-tree-core/branchCommitEnricher.js.map +1 -1
  288. package/lib/shared-tree-core/defaultResubmitMachine.d.ts.map +1 -1
  289. package/lib/shared-tree-core/defaultResubmitMachine.js +3 -2
  290. package/lib/shared-tree-core/defaultResubmitMachine.js.map +1 -1
  291. package/lib/shared-tree-core/editManager.d.ts.map +1 -1
  292. package/lib/shared-tree-core/editManager.js +1 -1
  293. package/lib/shared-tree-core/editManager.js.map +1 -1
  294. package/lib/shared-tree-core/index.d.ts +1 -1
  295. package/lib/shared-tree-core/index.d.ts.map +1 -1
  296. package/lib/shared-tree-core/index.js +1 -1
  297. package/lib/shared-tree-core/index.js.map +1 -1
  298. package/lib/shared-tree-core/sharedTreeCore.d.ts +2 -2
  299. package/lib/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
  300. package/lib/shared-tree-core/sharedTreeCore.js +12 -53
  301. package/lib/shared-tree-core/sharedTreeCore.js.map +1 -1
  302. package/lib/shared-tree-core/transaction.d.ts +108 -0
  303. package/lib/shared-tree-core/transaction.d.ts.map +1 -0
  304. package/lib/shared-tree-core/transaction.js +95 -0
  305. package/lib/shared-tree-core/transaction.js.map +1 -0
  306. package/lib/shared-tree-core/transactionEnricher.d.ts +8 -13
  307. package/lib/shared-tree-core/transactionEnricher.d.ts.map +1 -1
  308. package/lib/shared-tree-core/transactionEnricher.js +41 -21
  309. package/lib/shared-tree-core/transactionEnricher.js.map +1 -1
  310. package/lib/simple-tree/api/identifierIndex.d.ts +21 -0
  311. package/lib/simple-tree/api/identifierIndex.d.ts.map +1 -0
  312. package/lib/simple-tree/api/identifierIndex.js +41 -0
  313. package/lib/simple-tree/api/identifierIndex.js.map +1 -0
  314. package/lib/simple-tree/api/index.d.ts +2 -0
  315. package/lib/simple-tree/api/index.d.ts.map +1 -1
  316. package/lib/simple-tree/api/index.js +2 -0
  317. package/lib/simple-tree/api/index.js.map +1 -1
  318. package/lib/simple-tree/api/simpleSchemaToJsonSchema.js +11 -9
  319. package/lib/simple-tree/api/simpleSchemaToJsonSchema.js.map +1 -1
  320. package/lib/simple-tree/api/simpleTreeIndex.d.ts +65 -0
  321. package/lib/simple-tree/api/simpleTreeIndex.d.ts.map +1 -0
  322. package/lib/simple-tree/api/simpleTreeIndex.js +87 -0
  323. package/lib/simple-tree/api/simpleTreeIndex.js.map +1 -0
  324. package/lib/simple-tree/api/tree.d.ts +4 -5
  325. package/lib/simple-tree/api/tree.d.ts.map +1 -1
  326. package/lib/simple-tree/api/tree.js.map +1 -1
  327. package/lib/simple-tree/api/treeNodeApi.js.map +1 -1
  328. package/lib/simple-tree/core/index.d.ts +1 -1
  329. package/lib/simple-tree/core/index.d.ts.map +1 -1
  330. package/lib/simple-tree/core/index.js +1 -1
  331. package/lib/simple-tree/core/index.js.map +1 -1
  332. package/lib/simple-tree/core/treeNodeKernel.d.ts +6 -2
  333. package/lib/simple-tree/core/treeNodeKernel.d.ts.map +1 -1
  334. package/lib/simple-tree/core/treeNodeKernel.js +31 -1
  335. package/lib/simple-tree/core/treeNodeKernel.js.map +1 -1
  336. package/lib/simple-tree/core/unhydratedFlexTree.d.ts +1 -1
  337. package/lib/simple-tree/core/unhydratedFlexTree.d.ts.map +1 -1
  338. package/lib/simple-tree/core/unhydratedFlexTree.js +1 -1
  339. package/lib/simple-tree/core/unhydratedFlexTree.js.map +1 -1
  340. package/lib/simple-tree/index.d.ts +1 -1
  341. package/lib/simple-tree/index.d.ts.map +1 -1
  342. package/lib/simple-tree/index.js +1 -1
  343. package/lib/simple-tree/index.js.map +1 -1
  344. package/lib/simple-tree/objectNode.d.ts +7 -2
  345. package/lib/simple-tree/objectNode.d.ts.map +1 -1
  346. package/lib/simple-tree/objectNode.js.map +1 -1
  347. package/lib/simple-tree/toMapTree.js +5 -5
  348. package/lib/simple-tree/toMapTree.js.map +1 -1
  349. package/lib/util/index.d.ts +1 -2
  350. package/lib/util/index.d.ts.map +1 -1
  351. package/lib/util/index.js +1 -2
  352. package/lib/util/index.js.map +1 -1
  353. package/lib/util/typeCheck.d.ts +6 -1
  354. package/lib/util/typeCheck.d.ts.map +1 -1
  355. package/lib/util/typeCheck.js.map +1 -1
  356. package/lib/util/typeCheckTests.d.ts +14 -2
  357. package/lib/util/typeCheckTests.d.ts.map +1 -1
  358. package/lib/util/typeCheckTests.js.map +1 -1
  359. package/lib/util/utils.d.ts +29 -0
  360. package/lib/util/utils.d.ts.map +1 -1
  361. package/lib/util/utils.js +9 -0
  362. package/lib/util/utils.js.map +1 -1
  363. package/package.json +22 -22
  364. package/src/core/forest/forest.ts +12 -1
  365. package/src/core/index.ts +8 -1
  366. package/src/core/rebase/utils.ts +12 -10
  367. package/src/core/revertible.ts +35 -1
  368. package/src/core/schema-stored/storedSchemaRepository.ts +2 -1
  369. package/src/core/tree/anchorSet.ts +2 -1
  370. package/src/core/tree/detachedFieldIndexCodec.ts +4 -3
  371. package/src/core/tree/index.ts +1 -0
  372. package/src/core/tree/visitorUtils.ts +56 -1
  373. package/src/feature-libraries/chunked-forest/chunkedForest.ts +33 -7
  374. package/src/feature-libraries/chunked-forest/uniformChunk.ts +3 -3
  375. package/src/feature-libraries/flex-tree/context.ts +1 -1
  376. package/src/feature-libraries/index.ts +9 -0
  377. package/src/feature-libraries/indexing/anchorTreeIndex.ts +453 -0
  378. package/src/feature-libraries/indexing/index.ts +11 -0
  379. package/src/feature-libraries/indexing/types.ts +37 -0
  380. package/src/feature-libraries/object-forest/objectForest.ts +22 -4
  381. package/src/feature-libraries/sequence-field/invert.ts +4 -4
  382. package/src/feature-libraries/sequence-field/sequenceFieldToDelta.ts +4 -4
  383. package/src/index.ts +16 -6
  384. package/src/packageVersion.ts +1 -1
  385. package/src/shared-tree/index.ts +0 -2
  386. package/src/shared-tree/schematizingTreeView.ts +7 -7
  387. package/src/shared-tree/sharedTree.ts +60 -6
  388. package/src/shared-tree/sharedTreeChangeFamily.ts +5 -4
  389. package/src/shared-tree/treeCheckout.ts +186 -193
  390. package/src/shared-tree-core/branch.ts +93 -220
  391. package/src/shared-tree-core/branchCommitEnricher.ts +69 -64
  392. package/src/shared-tree-core/defaultResubmitMachine.ts +3 -2
  393. package/src/shared-tree-core/editManager.ts +1 -1
  394. package/src/shared-tree-core/index.ts +9 -2
  395. package/src/shared-tree-core/sharedTreeCore.ts +17 -62
  396. package/src/shared-tree-core/transaction.ts +165 -0
  397. package/src/shared-tree-core/transactionEnricher.ts +30 -24
  398. package/src/simple-tree/api/identifierIndex.ts +64 -0
  399. package/src/simple-tree/api/index.ts +5 -0
  400. package/src/simple-tree/api/simpleSchemaToJsonSchema.ts +17 -18
  401. package/src/simple-tree/api/simpleTreeIndex.ts +231 -0
  402. package/src/simple-tree/api/tree.ts +8 -5
  403. package/src/simple-tree/api/treeNodeApi.ts +1 -1
  404. package/src/simple-tree/core/index.ts +1 -0
  405. package/src/simple-tree/core/treeNodeKernel.ts +37 -2
  406. package/src/simple-tree/core/unhydratedFlexTree.ts +2 -1
  407. package/src/simple-tree/index.ts +4 -0
  408. package/src/simple-tree/objectNode.ts +19 -12
  409. package/src/simple-tree/toMapTree.ts +5 -5
  410. package/src/util/index.ts +3 -1
  411. package/src/util/typeCheck.ts +6 -1
  412. package/src/util/typeCheckTests.ts +11 -1
  413. package/src/util/utils.ts +38 -0
  414. package/dist/events/emitter.d.ts +0 -139
  415. package/dist/events/emitter.d.ts.map +0 -1
  416. package/dist/events/emitter.js +0 -165
  417. package/dist/events/emitter.js.map +0 -1
  418. package/dist/events/index.d.ts +0 -7
  419. package/dist/events/index.d.ts.map +0 -1
  420. package/dist/events/index.js +0 -11
  421. package/dist/events/index.js.map +0 -1
  422. package/dist/events/interop.d.ts +0 -30
  423. package/dist/events/interop.d.ts.map +0 -1
  424. package/dist/events/interop.js.map +0 -1
  425. package/dist/events/listeners.d.ts +0 -76
  426. package/dist/events/listeners.d.ts.map +0 -1
  427. package/dist/events/listeners.js +0 -7
  428. package/dist/events/listeners.js.map +0 -1
  429. package/dist/shared-tree-core/transactionStack.d.ts +0 -29
  430. package/dist/shared-tree-core/transactionStack.d.ts.map +0 -1
  431. package/dist/shared-tree-core/transactionStack.js +0 -41
  432. package/dist/shared-tree-core/transactionStack.js.map +0 -1
  433. package/dist/util/transactionResult.d.ts +0 -19
  434. package/dist/util/transactionResult.d.ts.map +0 -1
  435. package/dist/util/transactionResult.js +0 -23
  436. package/dist/util/transactionResult.js.map +0 -1
  437. package/lib/events/emitter.d.ts +0 -139
  438. package/lib/events/emitter.d.ts.map +0 -1
  439. package/lib/events/emitter.js +0 -160
  440. package/lib/events/emitter.js.map +0 -1
  441. package/lib/events/index.d.ts +0 -7
  442. package/lib/events/index.d.ts.map +0 -1
  443. package/lib/events/index.js.map +0 -1
  444. package/lib/events/interop.d.ts +0 -30
  445. package/lib/events/interop.d.ts.map +0 -1
  446. package/lib/events/interop.js.map +0 -1
  447. package/lib/events/listeners.d.ts +0 -76
  448. package/lib/events/listeners.d.ts.map +0 -1
  449. package/lib/events/listeners.js +0 -6
  450. package/lib/events/listeners.js.map +0 -1
  451. package/lib/shared-tree-core/transactionStack.d.ts +0 -29
  452. package/lib/shared-tree-core/transactionStack.d.ts.map +0 -1
  453. package/lib/shared-tree-core/transactionStack.js +0 -37
  454. package/lib/shared-tree-core/transactionStack.js.map +0 -1
  455. package/lib/util/transactionResult.d.ts +0 -19
  456. package/lib/util/transactionResult.d.ts.map +0 -1
  457. package/lib/util/transactionResult.js +0 -20
  458. package/lib/util/transactionResult.js.map +0 -1
  459. package/src/events/README.md +0 -3
  460. package/src/events/emitter.ts +0 -256
  461. package/src/events/index.ts +0 -19
  462. package/src/events/interop.ts +0 -38
  463. package/src/events/listeners.ts +0 -80
  464. package/src/shared-tree-core/transactionStack.ts +0 -45
  465. package/src/util/transactionResult.ts +0 -19
@@ -0,0 +1,453 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import { assert } from "@fluidframework/core-utils/internal";
7
+ import { disposeSymbol, fail, getOrCreate } from "../../util/index.js";
8
+ import {
9
+ type Anchor,
10
+ type AnchorNode,
11
+ type FieldKey,
12
+ type TreeNodeSchemaIdentifier,
13
+ forEachField,
14
+ forEachNode,
15
+ type ITreeSubscriptionCursor,
16
+ createAnnouncedVisitor,
17
+ type IForestSubscription,
18
+ type AnnouncedVisitor,
19
+ CursorLocationType,
20
+ rootField,
21
+ type UpPath,
22
+ type ProtoNodes,
23
+ keyAsDetachedField,
24
+ compareUpPaths,
25
+ TreeNavigationResult,
26
+ } from "../../core/index.js";
27
+ import type { TreeIndex, TreeIndexKey, TreeIndexNodes } from "./types.js";
28
+ import { TreeStatus } from "../flex-tree/index.js";
29
+
30
+ /**
31
+ * A function that gets the value to index a node on, must be pure and functional.
32
+ * The given cursor should point to the node that will be indexed.
33
+ *
34
+ * @returns a value the index will use as the key for the given node
35
+ *
36
+ * @remarks
37
+ * This function does not own the cursor in any way, it walks the cursor to find the key the node is indexed on
38
+ * but returns the cursor to the state it was in before being passed to the function. It should also not be disposed by this function
39
+ * and must be disposed elsewhere.
40
+ */
41
+ export type KeyFinder<TKey extends TreeIndexKey> = (tree: ITreeSubscriptionCursor) => TKey;
42
+
43
+ /**
44
+ * An index from some arbitrary keys to anchor nodes. Keys can be anything that is a {@link TreeValue}.
45
+ * A key can map to multiple nodes but each collection of nodes only results in a single value.
46
+ *
47
+ * @remarks
48
+ * Detached nodes are stored in the index but filtered out when any public facing apis are called. This means that
49
+ * calling {@link keys} will not include any keys that are stored in the index but only map to detached nodes.
50
+ */
51
+ export class AnchorTreeIndex<TKey extends TreeIndexKey, TValue>
52
+ implements TreeIndex<TKey, TValue>
53
+ {
54
+ public disposed = false;
55
+ /**
56
+ * Caches {@link KeyFinder}s for each schema definition. If a schema maps to null, it does not
57
+ * need to be considered at all for this index. This allows us to skip subtrees that aren't relevant
58
+ * as a performance optimization.
59
+ */
60
+ private readonly keyFinders = new Map<TreeNodeSchemaIdentifier, KeyFinder<TKey> | null>();
61
+ /**
62
+ * The actual index from keys to anchor nodes.
63
+ */
64
+ private readonly keyToNodes = new Map<TKey, AnchorNode[]>();
65
+ /**
66
+ * Maintained for efficient removal of anchor nodes from the index when updating their keys
67
+ */
68
+ private readonly nodeToKey = new Map<AnchorNode, TKey>();
69
+ /**
70
+ * Keeps track of anchors for disposal.
71
+ */
72
+ private readonly anchors = new Map<AnchorNode, Anchor[]>();
73
+ /**
74
+ * The key finder that is registered on the forest to keep this index updated, maintained
75
+ * here for deregistration on disposal
76
+ */
77
+ private readonly keyFinder = this.acquireVisitor.bind(this);
78
+
79
+ /**
80
+ * @param forest - the forest that is being indexed
81
+ * @param indexer - a function that retrieves the key finder based on a given schema or undefined if the schema does not have an associated key finder
82
+ * @param getValue - a pure and functional function that returns the associated value of one or more anchor nodes, can be used to map and filter the indexed anchor nodes
83
+ * so that the values returned from the index are more usable
84
+ * @param checkTreeStatus - a function that gets the tree status from an anchor node, used for filtering out detached nodes
85
+ */
86
+ public constructor(
87
+ private readonly forest: IForestSubscription,
88
+ private readonly indexer: (
89
+ schemaId: TreeNodeSchemaIdentifier,
90
+ ) => KeyFinder<TKey> | undefined,
91
+ private readonly getValue: (anchorNodes: TreeIndexNodes<AnchorNode>) => TValue | undefined,
92
+ private readonly checkTreeStatus: (node: AnchorNode) => TreeStatus | undefined,
93
+ ) {
94
+ this.forest.registerAnnouncedVisitor(this.keyFinder);
95
+
96
+ const detachedFieldKeys: FieldKey[] = [];
97
+ const detachedFieldsCursor = forest.getCursorAboveDetachedFields();
98
+ forEachField(detachedFieldsCursor, (field) => {
99
+ detachedFieldKeys.push(field.getFieldKey());
100
+ });
101
+
102
+ // index all existing trees (this includes the primary document tree and all other detached/removed trees)
103
+ for (const fieldKey of detachedFieldKeys) {
104
+ const cursor = forest.allocateCursor();
105
+ forest.tryMoveCursorToField({ fieldKey, parent: undefined }, cursor);
106
+ this.indexField(cursor);
107
+ cursor.free();
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Creates an announced visitor that responds to edits to the forest and updates the index accordingly.
113
+ */
114
+ private acquireVisitor(): AnnouncedVisitor {
115
+ this.checkNotDisposed(
116
+ "visitor getter should be deregistered from the forest when index is disposed",
117
+ );
118
+ let parentField: FieldKey | undefined;
119
+ let parent: UpPath | undefined;
120
+
121
+ return createAnnouncedVisitor({
122
+ // nodes (and their entire subtrees) are added to the index as soon as they are created
123
+ afterCreate: (content: ProtoNodes, destination: FieldKey) => {
124
+ const detachedCursor = this.forest.allocateCursor();
125
+ assert(
126
+ this.forest.tryMoveCursorToField(
127
+ { fieldKey: destination, parent: undefined },
128
+ detachedCursor,
129
+ ) === TreeNavigationResult.Ok,
130
+ 0xa8a /* destination of created nodes must be a valid detached field */,
131
+ );
132
+ this.indexField(detachedCursor);
133
+ detachedCursor.free();
134
+ },
135
+ // when a replace happens, the keys of previously indexed nodes could be changed so we must re-index them
136
+ afterReplace: () => {
137
+ assert(parent !== undefined, 0xa8b /* must have a parent */);
138
+ const cursor = this.forest.allocateCursor();
139
+ this.forest.moveCursorToPath(parent, cursor);
140
+ assert(
141
+ cursor.mode === CursorLocationType.Nodes,
142
+ 0xa8c /* replace should happen in a node */,
143
+ );
144
+ cursor.exitNode();
145
+ // we must re-index the spine because the key finders allow for any value under a subtree to be the key
146
+ // this means that a replace can cause the key for any node up its spine to be changed
147
+ this.indexSpine(cursor);
148
+ cursor.clear();
149
+ },
150
+ // the methods below are used to keep track of the path that has been traversed by the visitor
151
+ // this is required so that cursors can be moved to the correct location when index updates are required
152
+ enterNode(index: number): void {
153
+ assert(parentField !== undefined, 0xa8d /* must be in a field to enter node */);
154
+
155
+ parent = {
156
+ parent,
157
+ parentField,
158
+ parentIndex: index,
159
+ };
160
+ parentField = undefined;
161
+ },
162
+ exitNode(index: number): void {
163
+ assert(parent !== undefined, 0xa8e /* must have parent node */);
164
+ const temp = parent;
165
+ parentField = temp.parentField;
166
+ parent = temp.parent;
167
+ },
168
+ enterField: (key: FieldKey) => {
169
+ parentField = key;
170
+ },
171
+ exitField(key: FieldKey): void {
172
+ parentField = undefined;
173
+ },
174
+ });
175
+ }
176
+
177
+ /**
178
+ * Returns the value associated with the given key if it has been indexed
179
+ */
180
+ public get(key: TKey): TValue | undefined {
181
+ this.checkNotDisposed();
182
+ return this.getFilteredValue(this.keyToNodes.get(key));
183
+ }
184
+
185
+ /**
186
+ * Returns true iff the key exists in the index
187
+ */
188
+ public has(key: TKey): boolean {
189
+ this.checkNotDisposed();
190
+ return this.get(key) !== undefined;
191
+ }
192
+
193
+ /**
194
+ * Returns the number of values that are indexed
195
+ */
196
+ public get size(): number {
197
+ this.checkNotDisposed();
198
+ let s = 0;
199
+ for (const nodes of this.keyToNodes.values()) {
200
+ if (this.getFilteredValue(nodes) !== undefined) {
201
+ s += 1;
202
+ }
203
+ }
204
+ return s;
205
+ }
206
+
207
+ /**
208
+ * Returns all keys in the index
209
+ */
210
+ public *keys(): IterableIterator<TKey> {
211
+ this.checkNotDisposed();
212
+ for (const [key, nodes] of this.keyToNodes.entries()) {
213
+ if (this.getFilteredValue(nodes) !== undefined) {
214
+ yield key;
215
+ }
216
+ }
217
+ }
218
+
219
+ /**
220
+ * Returns an iterable of values in the index
221
+ */
222
+ public *values(): IterableIterator<TValue> {
223
+ this.checkNotDisposed();
224
+ for (const nodes of this.keyToNodes.values()) {
225
+ const filtered = this.getFilteredValue(nodes);
226
+ if (filtered !== undefined) {
227
+ yield filtered;
228
+ }
229
+ }
230
+ }
231
+
232
+ /**
233
+ * Returns an iterable of key, value pairs for every entry in the index
234
+ */
235
+ public *entries(): IterableIterator<[TKey, TValue]> {
236
+ this.checkNotDisposed();
237
+ for (const [key, nodes] of this.keyToNodes.entries()) {
238
+ const filtered = this.getFilteredValue(nodes);
239
+ if (filtered !== undefined) {
240
+ yield [key, filtered];
241
+ }
242
+ }
243
+ }
244
+
245
+ public [Symbol.iterator](): IterableIterator<[TKey, TValue]> {
246
+ this.checkNotDisposed();
247
+ return this.entries();
248
+ }
249
+
250
+ /**
251
+ * Applies the provided callback to each entry in the index.
252
+ */
253
+ public forEach(
254
+ callbackfn: (value: TValue, key: TKey, map: AnchorTreeIndex<TKey, TValue>) => void,
255
+ thisArg?: unknown,
256
+ ): void {
257
+ this.checkNotDisposed();
258
+ for (const [key, nodes] of this.keyToNodes.entries()) {
259
+ const filtered = this.getFilteredValue(nodes);
260
+ if (filtered !== undefined) {
261
+ callbackfn.call(thisArg, filtered, key, this);
262
+ }
263
+ }
264
+ }
265
+
266
+ /**
267
+ * Returns an iterable of key, value pairs for every entry in the index, including ones that are detached.
268
+ * This function should only be used for testing purposes, it is not exposed as part of the public {@link TreeIndex} API.
269
+ */
270
+ public *allEntries(): IterableIterator<[TKey, TValue]> {
271
+ this.checkNotDisposed();
272
+ for (const [key, nodes] of this.keyToNodes.entries()) {
273
+ const value = this.getValue(nodes as unknown as TreeIndexNodes<AnchorNode>);
274
+ if (value !== undefined) {
275
+ yield [key, value];
276
+ }
277
+ }
278
+ }
279
+
280
+ public dispose(): void {
281
+ this[disposeSymbol]();
282
+ }
283
+
284
+ /**
285
+ * Disposes this index and all the anchors it holds onto.
286
+ */
287
+ public [disposeSymbol](): void {
288
+ this.checkNotDisposed("index is already disposed");
289
+ for (const anchors of this.anchors.values()) {
290
+ for (const anchor of anchors) {
291
+ this.forest.forgetAnchor(anchor);
292
+ }
293
+ }
294
+ this.keyToNodes.clear();
295
+ this.anchors.clear();
296
+ this.forest.deregisterAnnouncedVisitor(this.keyFinder);
297
+ this.disposed = true;
298
+ }
299
+
300
+ private checkNotDisposed(errorMessage?: string): void {
301
+ if (this.disposed) {
302
+ if (errorMessage !== undefined) {
303
+ throw new Error(errorMessage);
304
+ }
305
+ assert(false, 0xa8f /* invalid operation on a disposed index */);
306
+ }
307
+ }
308
+
309
+ /**
310
+ * Given a cursor in node mode, indexes it.
311
+ */
312
+ private indexNode(nodeCursor: ITreeSubscriptionCursor): void {
313
+ const keyFinder = getOrCreate(
314
+ this.keyFinders,
315
+ // the node schema type to look up
316
+ nodeCursor.type,
317
+ // if the indexer does not return a key finder for this schema, we cache a null value to indicate the indexer
318
+ // does not need to be called if this schema is encountered in the future
319
+ (schema) => this.indexer(schema) ?? null,
320
+ );
321
+
322
+ if (keyFinder !== null) {
323
+ const expectedPath = nodeCursor.getPath();
324
+ const key = keyFinder(nodeCursor);
325
+ // TODO: determine perf impact of this check, alternative is not doing it in which case (if the key finder is not pure and functional),
326
+ // an error may be thrown further down the line if the structure of the nodes aren't expected or the contents of the index could be inaccurate
327
+ if (!compareUpPaths(nodeCursor.getPath(), expectedPath)) {
328
+ throw new Error("key finder should be pure and functional");
329
+ }
330
+ const anchor = nodeCursor.buildAnchor();
331
+ const anchorNode = this.forest.anchors.locate(anchor) ?? fail("expected anchor node");
332
+
333
+ // check if this anchor node already exists in the index
334
+ const existingKey = this.nodeToKey.get(anchorNode);
335
+ if (existingKey !== undefined) {
336
+ // if the node already exists but has the same key, we return early
337
+ if (existingKey === key) {
338
+ this.forest.forgetAnchor(anchor);
339
+ return;
340
+ } else {
341
+ // if the node has a different key, we remove the existing one first because it means the key had been detached
342
+ this.removeAnchor(anchorNode, existingKey);
343
+ }
344
+ }
345
+
346
+ getOrCreate(this.keyToNodes, key, () => []).push(anchorNode);
347
+ this.nodeToKey.set(anchorNode, key);
348
+
349
+ getOrCreate(this.anchors, anchorNode, () => []).push(anchor);
350
+ // when the anchor node is destroyed, delete it from the index
351
+ anchorNode.events.on("afterDestroy", () => {
352
+ this.removeAnchor(anchorNode, key);
353
+ });
354
+ }
355
+ }
356
+
357
+ /**
358
+ * Given a cursor in field mode, recursively indexes all nodes under the field.
359
+ */
360
+ private indexField(fieldCursor: ITreeSubscriptionCursor): void {
361
+ forEachNode(fieldCursor, (nodeCursor) => {
362
+ this.indexNode(nodeCursor);
363
+
364
+ forEachField(nodeCursor, (f) => {
365
+ this.indexField(f);
366
+ });
367
+ });
368
+ }
369
+
370
+ /**
371
+ * Given a cursor in field mode, indexes all nodes under the field and then indexes all nodes up the spine.
372
+ */
373
+ private indexSpine(cursor: ITreeSubscriptionCursor): void {
374
+ this.indexField(cursor);
375
+
376
+ if (keyAsDetachedField(cursor.getFieldKey()) !== rootField) {
377
+ cursor.exitField();
378
+ cursor.exitNode();
379
+ } else {
380
+ // return early if we're already at the root field
381
+ return;
382
+ }
383
+
384
+ // walk up the spine and index nodes until we reach the root
385
+ while (
386
+ cursor.mode === CursorLocationType.Fields &&
387
+ keyAsDetachedField(cursor.getFieldKey()) !== rootField
388
+ ) {
389
+ forEachNode(cursor, (nodeCursor) => {
390
+ this.indexNode(nodeCursor);
391
+ });
392
+
393
+ cursor.exitField();
394
+ cursor.exitNode();
395
+ }
396
+ }
397
+
398
+ private removeAnchor(anchorNode: AnchorNode, key: TKey): void {
399
+ const indexedNodes = this.keyToNodes.get(key);
400
+ assert(
401
+ indexedNodes !== undefined,
402
+ 0xa90 /* destroyed anchor node should be tracked by index */,
403
+ );
404
+ const index = indexedNodes.indexOf(anchorNode);
405
+ assert(index !== -1, 0xa91 /* destroyed anchor node should be tracked by index */);
406
+ const newNodes = filterNodes(indexedNodes, (n) => n !== anchorNode);
407
+ if (newNodes !== undefined && newNodes.length > 0) {
408
+ this.keyToNodes.set(key, newNodes);
409
+ } else {
410
+ this.keyToNodes.delete(key);
411
+ }
412
+ this.nodeToKey.delete(anchorNode);
413
+ assert(
414
+ this.anchors.delete(anchorNode),
415
+ 0xa92 /* destroyed anchor should be tracked by index */,
416
+ );
417
+ }
418
+
419
+ /**
420
+ * Filters out any anchor nodes that are detached and returns the value for the remaining nodes.
421
+ */
422
+ private getFilteredValue(anchorNodes: AnchorNode[] | undefined): TValue | undefined {
423
+ const attachedNodes = filterNodes(anchorNodes, (anchorNode) => {
424
+ const nodeStatus = this.checkTreeStatus(anchorNode);
425
+ return nodeStatus === TreeStatus.InDocument;
426
+ });
427
+
428
+ if (attachedNodes !== undefined && hasElement(attachedNodes)) {
429
+ return this.getValue(attachedNodes);
430
+ }
431
+ }
432
+ }
433
+
434
+ /**
435
+ * Filters the given anchor nodes based on the given filter function.
436
+ */
437
+ function filterNodes(
438
+ anchorNodes: readonly AnchorNode[] | undefined,
439
+ filter: (node: AnchorNode) => boolean,
440
+ ): AnchorNode[] | undefined {
441
+ if (anchorNodes !== undefined) {
442
+ return anchorNodes.filter(filter);
443
+ }
444
+
445
+ return undefined;
446
+ }
447
+
448
+ /**
449
+ * Checks that an array is of the type {@link TreeIndexNodes} and has at least one element.
450
+ */
451
+ export function hasElement<T>(array: readonly T[]): array is TreeIndexNodes<T> {
452
+ return array.length >= 1;
453
+ }
@@ -0,0 +1,11 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ export {
7
+ AnchorTreeIndex,
8
+ type KeyFinder,
9
+ hasElement,
10
+ } from "./anchorTreeIndex.js";
11
+ export type { TreeIndex, TreeIndexKey, TreeIndexNodes } from "./types.js";
@@ -0,0 +1,37 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import type { IFluidHandle } from "@fluidframework/core-interfaces";
7
+
8
+ /**
9
+ * an array of nodes that is guaranteed to have at least one element
10
+ *
11
+ * @alpha
12
+ */
13
+ export type TreeIndexNodes<TNode> = readonly [first: TNode, ...rest: TNode[]];
14
+
15
+ /**
16
+ * Value that may be used as keys in a {@link TreeIndex}.
17
+ *
18
+ * @privateRemarks
19
+ * no-new-null is disabled for this type so that it supports the TreeValue type.
20
+ *
21
+ * @alpha
22
+ */
23
+ // eslint-disable-next-line @rushstack/no-new-null
24
+ export type TreeIndexKey = number | string | boolean | IFluidHandle | null;
25
+
26
+ /**
27
+ * A index where values are keyed on {@link TreeIndexKey}s.
28
+ *
29
+ * @alpha
30
+ */
31
+ export interface TreeIndex<TKey extends TreeIndexKey, TValue>
32
+ extends ReadonlyMap<TKey, TValue> {
33
+ /**
34
+ * Disposes the index such that it can no longer be used and receives no updates from the forest
35
+ */
36
+ dispose(): void;
37
+ }
@@ -4,10 +4,13 @@
4
4
  */
5
5
 
6
6
  import { assert } from "@fluidframework/core-utils/internal";
7
+ import { createEmitter } from "@fluid-internal/client-utils";
8
+ import type { Listenable } from "@fluidframework/core-interfaces";
7
9
 
8
10
  import {
9
11
  type Anchor,
10
12
  AnchorSet,
13
+ type AnnouncedVisitor,
11
14
  type CursorLocationType,
12
15
  type DeltaVisitor,
13
16
  type DetachedField,
@@ -31,9 +34,9 @@ import {
31
34
  type UpPath,
32
35
  type Value,
33
36
  aboveRootPlaceholder,
37
+ combineVisitors,
34
38
  deepCopyMapTree,
35
39
  } from "../../core/index.js";
36
- import { createEmitter, type Listenable } from "../../events/index.js";
37
40
  import {
38
41
  assertNonNegativeSafeInteger,
39
42
  assertValidIndex,
@@ -72,6 +75,7 @@ export class ObjectForest implements IEditableForest {
72
75
 
73
76
  // All cursors that are in the "Current" state. Must be empty when editing.
74
77
  public readonly currentCursors: Set<Cursor> = new Set();
78
+ private readonly deltaVisitors: Set<() => AnnouncedVisitor> = new Set();
75
79
 
76
80
  readonly #events = createEmitter<ForestEvents>();
77
81
  public readonly events: Listenable<ForestEvents> = this.#events;
@@ -254,9 +258,23 @@ export class ObjectForest implements IEditableForest {
254
258
  }
255
259
  }
256
260
 
257
- const visitor = new Visitor(this);
258
- this.activeVisitor = visitor;
259
- return visitor;
261
+ const forestVisitor = new Visitor(this);
262
+ const announcedVisitors: AnnouncedVisitor[] = [];
263
+ this.deltaVisitors.forEach((getVisitor) => announcedVisitors.push(getVisitor()));
264
+ const combinedVisitor = combineVisitors(
265
+ [forestVisitor, ...announcedVisitors],
266
+ announcedVisitors,
267
+ );
268
+ this.activeVisitor = combinedVisitor;
269
+ return combinedVisitor;
270
+ }
271
+
272
+ public registerAnnouncedVisitor(visitor: () => AnnouncedVisitor): void {
273
+ this.deltaVisitors.add(visitor);
274
+ }
275
+
276
+ public deregisterAnnouncedVisitor(visitor: () => AnnouncedVisitor): void {
277
+ this.deltaVisitors.delete(visitor);
260
278
  }
261
279
 
262
280
  private nextRange = 0;
@@ -3,10 +3,10 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { assert, unreachableCase, oob } from "@fluidframework/core-utils/internal";
6
+ import { assert, unreachableCase } from "@fluidframework/core-utils/internal";
7
7
 
8
8
  import type { RevisionTag } from "../../core/index.js";
9
- import { type IdAllocator, type Mutable, fail } from "../../util/index.js";
9
+ import { type IdAllocator, type Mutable, fail, hasSingle } from "../../util/index.js";
10
10
  import {
11
11
  type CrossFieldManager,
12
12
  CrossFieldTarget,
@@ -257,11 +257,11 @@ function invertMark(
257
257
  }
258
258
 
259
259
  assert(
260
- detachInverses.length === 1,
260
+ hasSingle(detachInverses),
261
261
  0x80d /* Only expected MoveIn marks to be split when inverting */,
262
262
  );
263
263
 
264
- let detachInverse = detachInverses[0] ?? oob();
264
+ let detachInverse = detachInverses[0];
265
265
  assert(isAttach(detachInverse), 0x80e /* Inverse of a detach should be an attach */);
266
266
 
267
267
  const inverses: Mark[] = [];
@@ -3,7 +3,7 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { assert, unreachableCase, oob } from "@fluidframework/core-utils/internal";
6
+ import { assert, unreachableCase } from "@fluidframework/core-utils/internal";
7
7
 
8
8
  import {
9
9
  type DeltaDetachedNodeChanges,
@@ -12,7 +12,7 @@ import {
12
12
  type DeltaMark,
13
13
  areEqualChangeAtomIds,
14
14
  } from "../../core/index.js";
15
- import type { Mutable } from "../../util/index.js";
15
+ import { getLast, hasSome, type Mutable } from "../../util/index.js";
16
16
  import { nodeIdFromChangeAtom } from "../deltaUtils.js";
17
17
 
18
18
  import { isMoveIn, isMoveOut } from "./moveEffectTable.js";
@@ -176,8 +176,8 @@ export function sequenceFieldToDelta(
176
176
  }
177
177
  }
178
178
  // Remove trailing no-op marks
179
- while (local.length > 0) {
180
- const lastMark = local[local.length - 1] ?? oob();
179
+ while (hasSome(local)) {
180
+ const lastMark = getLast(local);
181
181
  if (
182
182
  lastMark.attach !== undefined ||
183
183
  lastMark.detach !== undefined ||
package/src/index.ts CHANGED
@@ -29,19 +29,24 @@ export {
29
29
  MapNodeStoredSchema,
30
30
  LeafNodeStoredSchema,
31
31
  type RevertibleFactory,
32
+ type RevertibleAlphaFactory,
33
+ type RevertibleAlpha,
32
34
  } from "./core/index.js";
33
35
  export { type Brand } from "./util/index.js";
34
36
 
35
- export {
36
- type Listeners,
37
- type IsListener,
38
- type Listenable,
39
- type Off,
40
- } from "./events/index.js";
37
+ export type {
38
+ Listeners,
39
+ IsListener,
40
+ Listenable,
41
+ Off,
42
+ } from "@fluidframework/core-interfaces";
41
43
 
42
44
  export {
43
45
  TreeStatus,
44
46
  TreeCompressionStrategy,
47
+ type TreeIndex,
48
+ type TreeIndexKey,
49
+ type TreeIndexNodes,
45
50
  } from "./feature-libraries/index.js";
46
51
 
47
52
  export {
@@ -126,6 +131,11 @@ export {
126
131
  // Recursive Schema APIs
127
132
  type ValidateRecursiveSchema,
128
133
  type FixRecursiveArraySchema,
134
+ // Index APIs
135
+ type SimpleTreeIndex,
136
+ type IdentifierIndex,
137
+ createSimpleTreeIndex,
138
+ createIdentifierIndex,
129
139
  // experimental @alpha APIs:
130
140
  adaptEnum,
131
141
  enumFromStrings,
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/tree";
9
- export const pkgVersion = "2.10.0";
9
+ export const pkgVersion = "2.11.0";
@@ -22,9 +22,7 @@ export {
22
22
  createTreeCheckout,
23
23
  TreeCheckout,
24
24
  type ITreeCheckout,
25
- runSynchronous,
26
25
  type CheckoutEvents,
27
- type ITransaction,
28
26
  type ITreeCheckoutFork,
29
27
  type BranchableTree,
30
28
  type TreeBranchFork,