@fluidframework/tree 2.12.0 → 2.20.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 (496) hide show
  1. package/CHANGELOG.md +154 -0
  2. package/api-report/tree.alpha.api.md +108 -22
  3. package/api-report/tree.beta.api.md +31 -15
  4. package/api-report/tree.legacy.alpha.api.md +31 -15
  5. package/api-report/tree.legacy.public.api.md +31 -15
  6. package/api-report/tree.public.api.md +31 -15
  7. package/assertTagging.config.mjs +14 -0
  8. package/dist/alpha.d.ts +14 -0
  9. package/dist/beta.d.ts +2 -0
  10. package/dist/core/index.d.ts +2 -2
  11. package/dist/core/index.d.ts.map +1 -1
  12. package/dist/core/index.js +6 -4
  13. package/dist/core/index.js.map +1 -1
  14. package/dist/core/rebase/index.d.ts +2 -2
  15. package/dist/core/rebase/index.d.ts.map +1 -1
  16. package/dist/core/rebase/index.js +5 -1
  17. package/dist/core/rebase/index.js.map +1 -1
  18. package/dist/core/rebase/types.d.ts +5 -4
  19. package/dist/core/rebase/types.d.ts.map +1 -1
  20. package/dist/core/rebase/types.js +29 -1
  21. package/dist/core/rebase/types.js.map +1 -1
  22. package/dist/core/rebase/utils.d.ts +10 -0
  23. package/dist/core/rebase/utils.d.ts.map +1 -1
  24. package/dist/core/rebase/utils.js +22 -1
  25. package/dist/core/rebase/utils.js.map +1 -1
  26. package/dist/core/tree/delta.d.ts +21 -26
  27. package/dist/core/tree/delta.d.ts.map +1 -1
  28. package/dist/core/tree/delta.js.map +1 -1
  29. package/dist/core/tree/deltaUtil.d.ts +1 -3
  30. package/dist/core/tree/deltaUtil.d.ts.map +1 -1
  31. package/dist/core/tree/deltaUtil.js +2 -14
  32. package/dist/core/tree/deltaUtil.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 +1 -3
  36. package/dist/core/tree/index.js.map +1 -1
  37. package/dist/core/tree/visitDelta.d.ts.map +1 -1
  38. package/dist/core/tree/visitDelta.js +82 -80
  39. package/dist/core/tree/visitDelta.js.map +1 -1
  40. package/dist/feature-libraries/default-schema/defaultEditBuilder.d.ts +10 -0
  41. package/dist/feature-libraries/default-schema/defaultEditBuilder.d.ts.map +1 -1
  42. package/dist/feature-libraries/default-schema/defaultEditBuilder.js +3 -0
  43. package/dist/feature-libraries/default-schema/defaultEditBuilder.js.map +1 -1
  44. package/dist/feature-libraries/default-schema/defaultFieldKinds.d.ts.map +1 -1
  45. package/dist/feature-libraries/default-schema/defaultFieldKinds.js.map +1 -1
  46. package/dist/feature-libraries/deltaUtils.d.ts.map +1 -1
  47. package/dist/feature-libraries/deltaUtils.js +13 -0
  48. package/dist/feature-libraries/deltaUtils.js.map +1 -1
  49. package/dist/feature-libraries/forest-summary/forestSummarizer.d.ts.map +1 -1
  50. package/dist/feature-libraries/forest-summary/forestSummarizer.js +1 -6
  51. package/dist/feature-libraries/forest-summary/forestSummarizer.js.map +1 -1
  52. package/dist/feature-libraries/index.d.ts +0 -1
  53. package/dist/feature-libraries/index.d.ts.map +1 -1
  54. package/dist/feature-libraries/index.js +2 -4
  55. package/dist/feature-libraries/index.js.map +1 -1
  56. package/dist/feature-libraries/modular-schema/crossFieldQueries.d.ts +5 -5
  57. package/dist/feature-libraries/modular-schema/crossFieldQueries.d.ts.map +1 -1
  58. package/dist/feature-libraries/modular-schema/crossFieldQueries.js +2 -3
  59. package/dist/feature-libraries/modular-schema/crossFieldQueries.js.map +1 -1
  60. package/dist/feature-libraries/modular-schema/fieldChangeHandler.d.ts +30 -6
  61. package/dist/feature-libraries/modular-schema/fieldChangeHandler.d.ts.map +1 -1
  62. package/dist/feature-libraries/modular-schema/fieldChangeHandler.js.map +1 -1
  63. package/dist/feature-libraries/modular-schema/genericFieldKind.d.ts.map +1 -1
  64. package/dist/feature-libraries/modular-schema/genericFieldKind.js +2 -1
  65. package/dist/feature-libraries/modular-schema/genericFieldKind.js.map +1 -1
  66. package/dist/feature-libraries/modular-schema/index.d.ts +2 -2
  67. package/dist/feature-libraries/modular-schema/index.d.ts.map +1 -1
  68. package/dist/feature-libraries/modular-schema/index.js.map +1 -1
  69. package/dist/feature-libraries/modular-schema/modularChangeCodecs.d.ts +1 -1
  70. package/dist/feature-libraries/modular-schema/modularChangeCodecs.d.ts.map +1 -1
  71. package/dist/feature-libraries/modular-schema/modularChangeCodecs.js +8 -8
  72. package/dist/feature-libraries/modular-schema/modularChangeCodecs.js.map +1 -1
  73. package/dist/feature-libraries/modular-schema/modularChangeFamily.d.ts +5 -4
  74. package/dist/feature-libraries/modular-schema/modularChangeFamily.d.ts.map +1 -1
  75. package/dist/feature-libraries/modular-schema/modularChangeFamily.js +186 -216
  76. package/dist/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
  77. package/dist/feature-libraries/modular-schema/modularChangeTypes.d.ts +23 -20
  78. package/dist/feature-libraries/modular-schema/modularChangeTypes.d.ts.map +1 -1
  79. package/dist/feature-libraries/modular-schema/modularChangeTypes.js +20 -0
  80. package/dist/feature-libraries/modular-schema/modularChangeTypes.js.map +1 -1
  81. package/dist/feature-libraries/optional-field/optionalField.d.ts +3 -3
  82. package/dist/feature-libraries/optional-field/optionalField.d.ts.map +1 -1
  83. package/dist/feature-libraries/optional-field/optionalField.js +24 -4
  84. package/dist/feature-libraries/optional-field/optionalField.js.map +1 -1
  85. package/dist/feature-libraries/sequence-field/moveEffectTable.d.ts +1 -1
  86. package/dist/feature-libraries/sequence-field/moveEffectTable.d.ts.map +1 -1
  87. package/dist/feature-libraries/sequence-field/moveEffectTable.js.map +1 -1
  88. package/dist/feature-libraries/sequence-field/rebase.js +4 -4
  89. package/dist/feature-libraries/sequence-field/rebase.js.map +1 -1
  90. package/dist/feature-libraries/sequence-field/sequenceFieldCodecV1.js +1 -1
  91. package/dist/feature-libraries/sequence-field/sequenceFieldCodecV1.js.map +1 -1
  92. package/dist/feature-libraries/sequence-field/sequenceFieldCodecV2.js +1 -1
  93. package/dist/feature-libraries/sequence-field/sequenceFieldCodecV2.js.map +1 -1
  94. package/dist/feature-libraries/sequence-field/sequenceFieldToDelta.d.ts +2 -3
  95. package/dist/feature-libraries/sequence-field/sequenceFieldToDelta.d.ts.map +1 -1
  96. package/dist/feature-libraries/sequence-field/sequenceFieldToDelta.js.map +1 -1
  97. package/dist/feature-libraries/sequence-field/utils.d.ts +2 -2
  98. package/dist/feature-libraries/sequence-field/utils.d.ts.map +1 -1
  99. package/dist/feature-libraries/sequence-field/utils.js +50 -9
  100. package/dist/feature-libraries/sequence-field/utils.js.map +1 -1
  101. package/dist/feature-libraries/treeCursorUtils.d.ts.map +1 -1
  102. package/dist/feature-libraries/treeCursorUtils.js +4 -1
  103. package/dist/feature-libraries/treeCursorUtils.js.map +1 -1
  104. package/dist/index.d.ts +27 -3
  105. package/dist/index.d.ts.map +1 -1
  106. package/dist/index.js +5 -2
  107. package/dist/index.js.map +1 -1
  108. package/dist/legacy.d.ts +2 -0
  109. package/dist/package.json +2 -1
  110. package/dist/packageVersion.d.ts +1 -1
  111. package/dist/packageVersion.js +1 -1
  112. package/dist/packageVersion.js.map +1 -1
  113. package/dist/public.d.ts +2 -0
  114. package/dist/shared-tree/index.d.ts +3 -2
  115. package/dist/shared-tree/index.d.ts.map +1 -1
  116. package/dist/shared-tree/index.js +6 -3
  117. package/dist/shared-tree/index.js.map +1 -1
  118. package/dist/shared-tree/schematizingTreeView.d.ts +10 -1
  119. package/dist/shared-tree/schematizingTreeView.d.ts.map +1 -1
  120. package/dist/shared-tree/schematizingTreeView.js +43 -0
  121. package/dist/shared-tree/schematizingTreeView.js.map +1 -1
  122. package/dist/shared-tree/sharedTree.d.ts +44 -21
  123. package/dist/shared-tree/sharedTree.d.ts.map +1 -1
  124. package/dist/shared-tree/sharedTree.js +41 -35
  125. package/dist/shared-tree/sharedTree.js.map +1 -1
  126. package/dist/shared-tree/transactionTypes.d.ts +105 -0
  127. package/dist/shared-tree/transactionTypes.d.ts.map +1 -0
  128. package/dist/shared-tree/transactionTypes.js +13 -0
  129. package/dist/shared-tree/transactionTypes.js.map +1 -0
  130. package/dist/shared-tree/treeApi.d.ts +1 -25
  131. package/dist/shared-tree/treeApi.d.ts.map +1 -1
  132. package/dist/shared-tree/treeApi.js +4 -8
  133. package/dist/shared-tree/treeApi.js.map +1 -1
  134. package/dist/shared-tree/treeCheckout.d.ts +4 -1
  135. package/dist/shared-tree/treeCheckout.d.ts.map +1 -1
  136. package/dist/shared-tree/treeCheckout.js +142 -23
  137. package/dist/shared-tree/treeCheckout.js.map +1 -1
  138. package/dist/shared-tree-core/sharedTreeCore.js +1 -1
  139. package/dist/shared-tree-core/sharedTreeCore.js.map +1 -1
  140. package/dist/simple-tree/api/index.d.ts +1 -0
  141. package/dist/simple-tree/api/index.d.ts.map +1 -1
  142. package/dist/simple-tree/api/index.js +3 -1
  143. package/dist/simple-tree/api/index.js.map +1 -1
  144. package/dist/simple-tree/api/jsonSchema.d.ts +6 -0
  145. package/dist/simple-tree/api/jsonSchema.d.ts.map +1 -1
  146. package/dist/simple-tree/api/jsonSchema.js.map +1 -1
  147. package/dist/simple-tree/api/schemaFactory.d.ts +21 -12
  148. package/dist/simple-tree/api/schemaFactory.d.ts.map +1 -1
  149. package/dist/simple-tree/api/schemaFactory.js +5 -2
  150. package/dist/simple-tree/api/schemaFactory.js.map +1 -1
  151. package/dist/simple-tree/api/schemaFactoryAlpha.d.ts +83 -0
  152. package/dist/simple-tree/api/schemaFactoryAlpha.d.ts.map +1 -0
  153. package/dist/simple-tree/api/schemaFactoryAlpha.js +90 -0
  154. package/dist/simple-tree/api/schemaFactoryAlpha.js.map +1 -0
  155. package/dist/simple-tree/api/simpleSchema.d.ts +5 -1
  156. package/dist/simple-tree/api/simpleSchema.d.ts.map +1 -1
  157. package/dist/simple-tree/api/simpleSchema.js.map +1 -1
  158. package/dist/simple-tree/api/simpleSchemaToJsonSchema.js +13 -10
  159. package/dist/simple-tree/api/simpleSchemaToJsonSchema.js.map +1 -1
  160. package/dist/simple-tree/api/testRecursiveDomain.d.ts +5 -5
  161. package/dist/simple-tree/api/tree.d.ts +60 -0
  162. package/dist/simple-tree/api/tree.d.ts.map +1 -1
  163. package/dist/simple-tree/api/tree.js.map +1 -1
  164. package/dist/simple-tree/api/treeNodeApi.js +1 -1
  165. package/dist/simple-tree/api/treeNodeApi.js.map +1 -1
  166. package/dist/simple-tree/api/viewSchemaToSimpleSchema.d.ts.map +1 -1
  167. package/dist/simple-tree/api/viewSchemaToSimpleSchema.js +11 -11
  168. package/dist/simple-tree/api/viewSchemaToSimpleSchema.js.map +1 -1
  169. package/dist/simple-tree/arrayNode.d.ts +2 -2
  170. package/dist/simple-tree/arrayNode.d.ts.map +1 -1
  171. package/dist/simple-tree/arrayNode.js +3 -2
  172. package/dist/simple-tree/arrayNode.js.map +1 -1
  173. package/dist/simple-tree/core/treeNodeSchema.d.ts +10 -6
  174. package/dist/simple-tree/core/treeNodeSchema.d.ts.map +1 -1
  175. package/dist/simple-tree/core/treeNodeSchema.js.map +1 -1
  176. package/dist/simple-tree/index.d.ts +2 -2
  177. package/dist/simple-tree/index.d.ts.map +1 -1
  178. package/dist/simple-tree/index.js +3 -2
  179. package/dist/simple-tree/index.js.map +1 -1
  180. package/dist/simple-tree/leafNodeSchema.d.ts +5 -5
  181. package/dist/simple-tree/leafNodeSchema.d.ts.map +1 -1
  182. package/dist/simple-tree/mapNode.d.ts +2 -2
  183. package/dist/simple-tree/mapNode.d.ts.map +1 -1
  184. package/dist/simple-tree/mapNode.js +2 -1
  185. package/dist/simple-tree/mapNode.js.map +1 -1
  186. package/dist/simple-tree/objectNode.d.ts +2 -2
  187. package/dist/simple-tree/objectNode.d.ts.map +1 -1
  188. package/dist/simple-tree/objectNode.js +2 -1
  189. package/dist/simple-tree/objectNode.js.map +1 -1
  190. package/dist/simple-tree/objectNodeTypes.d.ts +2 -2
  191. package/dist/simple-tree/objectNodeTypes.d.ts.map +1 -1
  192. package/dist/simple-tree/objectNodeTypes.js.map +1 -1
  193. package/dist/simple-tree/schemaTypes.d.ts +47 -1
  194. package/dist/simple-tree/schemaTypes.d.ts.map +1 -1
  195. package/dist/simple-tree/schemaTypes.js.map +1 -1
  196. package/dist/simple-tree/toMapTree.js +1 -1
  197. package/dist/simple-tree/toMapTree.js.map +1 -1
  198. package/dist/util/bTreeUtils.d.ts +10 -0
  199. package/dist/util/bTreeUtils.d.ts.map +1 -0
  200. package/dist/util/bTreeUtils.js +52 -0
  201. package/dist/util/bTreeUtils.js.map +1 -0
  202. package/dist/util/idAllocator.d.ts +0 -2
  203. package/dist/util/idAllocator.d.ts.map +1 -1
  204. package/dist/util/idAllocator.js +0 -2
  205. package/dist/util/idAllocator.js.map +1 -1
  206. package/dist/util/index.d.ts +3 -2
  207. package/dist/util/index.d.ts.map +1 -1
  208. package/dist/util/index.js +7 -5
  209. package/dist/util/index.js.map +1 -1
  210. package/dist/util/rangeMap.d.ts +95 -43
  211. package/dist/util/rangeMap.d.ts.map +1 -1
  212. package/dist/util/rangeMap.js +202 -148
  213. package/dist/util/rangeMap.js.map +1 -1
  214. package/dist/util/utils.d.ts +26 -2
  215. package/dist/util/utils.d.ts.map +1 -1
  216. package/dist/util/utils.js +17 -2
  217. package/dist/util/utils.js.map +1 -1
  218. package/lib/alpha.d.ts +14 -0
  219. package/lib/beta.d.ts +2 -0
  220. package/lib/core/index.d.ts +2 -2
  221. package/lib/core/index.d.ts.map +1 -1
  222. package/lib/core/index.js +2 -2
  223. package/lib/core/index.js.map +1 -1
  224. package/lib/core/rebase/index.d.ts +2 -2
  225. package/lib/core/rebase/index.d.ts.map +1 -1
  226. package/lib/core/rebase/index.js +2 -2
  227. package/lib/core/rebase/index.js.map +1 -1
  228. package/lib/core/rebase/types.d.ts +5 -4
  229. package/lib/core/rebase/types.d.ts.map +1 -1
  230. package/lib/core/rebase/types.js +26 -1
  231. package/lib/core/rebase/types.js.map +1 -1
  232. package/lib/core/rebase/utils.d.ts +10 -0
  233. package/lib/core/rebase/utils.d.ts.map +1 -1
  234. package/lib/core/rebase/utils.js +20 -0
  235. package/lib/core/rebase/utils.js.map +1 -1
  236. package/lib/core/tree/delta.d.ts +21 -26
  237. package/lib/core/tree/delta.d.ts.map +1 -1
  238. package/lib/core/tree/delta.js.map +1 -1
  239. package/lib/core/tree/deltaUtil.d.ts +1 -3
  240. package/lib/core/tree/deltaUtil.d.ts.map +1 -1
  241. package/lib/core/tree/deltaUtil.js +1 -12
  242. package/lib/core/tree/deltaUtil.js.map +1 -1
  243. package/lib/core/tree/index.d.ts +1 -1
  244. package/lib/core/tree/index.d.ts.map +1 -1
  245. package/lib/core/tree/index.js +1 -1
  246. package/lib/core/tree/index.js.map +1 -1
  247. package/lib/core/tree/visitDelta.d.ts.map +1 -1
  248. package/lib/core/tree/visitDelta.js +82 -80
  249. package/lib/core/tree/visitDelta.js.map +1 -1
  250. package/lib/feature-libraries/default-schema/defaultEditBuilder.d.ts +10 -0
  251. package/lib/feature-libraries/default-schema/defaultEditBuilder.d.ts.map +1 -1
  252. package/lib/feature-libraries/default-schema/defaultEditBuilder.js +3 -0
  253. package/lib/feature-libraries/default-schema/defaultEditBuilder.js.map +1 -1
  254. package/lib/feature-libraries/default-schema/defaultFieldKinds.d.ts.map +1 -1
  255. package/lib/feature-libraries/default-schema/defaultFieldKinds.js.map +1 -1
  256. package/lib/feature-libraries/deltaUtils.d.ts.map +1 -1
  257. package/lib/feature-libraries/deltaUtils.js +13 -0
  258. package/lib/feature-libraries/deltaUtils.js.map +1 -1
  259. package/lib/feature-libraries/forest-summary/forestSummarizer.d.ts.map +1 -1
  260. package/lib/feature-libraries/forest-summary/forestSummarizer.js +1 -6
  261. package/lib/feature-libraries/forest-summary/forestSummarizer.js.map +1 -1
  262. package/lib/feature-libraries/index.d.ts +0 -1
  263. package/lib/feature-libraries/index.d.ts.map +1 -1
  264. package/lib/feature-libraries/index.js +0 -1
  265. package/lib/feature-libraries/index.js.map +1 -1
  266. package/lib/feature-libraries/modular-schema/crossFieldQueries.d.ts +5 -5
  267. package/lib/feature-libraries/modular-schema/crossFieldQueries.d.ts.map +1 -1
  268. package/lib/feature-libraries/modular-schema/crossFieldQueries.js +2 -3
  269. package/lib/feature-libraries/modular-schema/crossFieldQueries.js.map +1 -1
  270. package/lib/feature-libraries/modular-schema/fieldChangeHandler.d.ts +30 -6
  271. package/lib/feature-libraries/modular-schema/fieldChangeHandler.d.ts.map +1 -1
  272. package/lib/feature-libraries/modular-schema/fieldChangeHandler.js.map +1 -1
  273. package/lib/feature-libraries/modular-schema/genericFieldKind.d.ts.map +1 -1
  274. package/lib/feature-libraries/modular-schema/genericFieldKind.js +2 -1
  275. package/lib/feature-libraries/modular-schema/genericFieldKind.js.map +1 -1
  276. package/lib/feature-libraries/modular-schema/index.d.ts +2 -2
  277. package/lib/feature-libraries/modular-schema/index.d.ts.map +1 -1
  278. package/lib/feature-libraries/modular-schema/index.js.map +1 -1
  279. package/lib/feature-libraries/modular-schema/modularChangeCodecs.d.ts +1 -1
  280. package/lib/feature-libraries/modular-schema/modularChangeCodecs.d.ts.map +1 -1
  281. package/lib/feature-libraries/modular-schema/modularChangeCodecs.js +4 -4
  282. package/lib/feature-libraries/modular-schema/modularChangeCodecs.js.map +1 -1
  283. package/lib/feature-libraries/modular-schema/modularChangeFamily.d.ts +5 -4
  284. package/lib/feature-libraries/modular-schema/modularChangeFamily.d.ts.map +1 -1
  285. package/lib/feature-libraries/modular-schema/modularChangeFamily.js +158 -186
  286. package/lib/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
  287. package/lib/feature-libraries/modular-schema/modularChangeTypes.d.ts +23 -20
  288. package/lib/feature-libraries/modular-schema/modularChangeTypes.d.ts.map +1 -1
  289. package/lib/feature-libraries/modular-schema/modularChangeTypes.js +18 -1
  290. package/lib/feature-libraries/modular-schema/modularChangeTypes.js.map +1 -1
  291. package/lib/feature-libraries/optional-field/optionalField.d.ts +3 -3
  292. package/lib/feature-libraries/optional-field/optionalField.d.ts.map +1 -1
  293. package/lib/feature-libraries/optional-field/optionalField.js +24 -4
  294. package/lib/feature-libraries/optional-field/optionalField.js.map +1 -1
  295. package/lib/feature-libraries/sequence-field/moveEffectTable.d.ts +1 -1
  296. package/lib/feature-libraries/sequence-field/moveEffectTable.d.ts.map +1 -1
  297. package/lib/feature-libraries/sequence-field/moveEffectTable.js.map +1 -1
  298. package/lib/feature-libraries/sequence-field/rebase.js +4 -4
  299. package/lib/feature-libraries/sequence-field/rebase.js.map +1 -1
  300. package/lib/feature-libraries/sequence-field/sequenceFieldCodecV1.js +1 -1
  301. package/lib/feature-libraries/sequence-field/sequenceFieldCodecV1.js.map +1 -1
  302. package/lib/feature-libraries/sequence-field/sequenceFieldCodecV2.js +1 -1
  303. package/lib/feature-libraries/sequence-field/sequenceFieldCodecV2.js.map +1 -1
  304. package/lib/feature-libraries/sequence-field/sequenceFieldToDelta.d.ts +2 -3
  305. package/lib/feature-libraries/sequence-field/sequenceFieldToDelta.d.ts.map +1 -1
  306. package/lib/feature-libraries/sequence-field/sequenceFieldToDelta.js.map +1 -1
  307. package/lib/feature-libraries/sequence-field/utils.d.ts +2 -2
  308. package/lib/feature-libraries/sequence-field/utils.d.ts.map +1 -1
  309. package/lib/feature-libraries/sequence-field/utils.js +50 -9
  310. package/lib/feature-libraries/sequence-field/utils.js.map +1 -1
  311. package/lib/feature-libraries/treeCursorUtils.d.ts.map +1 -1
  312. package/lib/feature-libraries/treeCursorUtils.js +4 -1
  313. package/lib/feature-libraries/treeCursorUtils.js.map +1 -1
  314. package/lib/index.d.ts +27 -3
  315. package/lib/index.d.ts.map +1 -1
  316. package/lib/index.js +2 -2
  317. package/lib/index.js.map +1 -1
  318. package/lib/legacy.d.ts +2 -0
  319. package/lib/packageVersion.d.ts +1 -1
  320. package/lib/packageVersion.js +1 -1
  321. package/lib/packageVersion.js.map +1 -1
  322. package/lib/public.d.ts +2 -0
  323. package/lib/shared-tree/index.d.ts +3 -2
  324. package/lib/shared-tree/index.d.ts.map +1 -1
  325. package/lib/shared-tree/index.js +3 -2
  326. package/lib/shared-tree/index.js.map +1 -1
  327. package/lib/shared-tree/schematizingTreeView.d.ts +10 -1
  328. package/lib/shared-tree/schematizingTreeView.d.ts.map +1 -1
  329. package/lib/shared-tree/schematizingTreeView.js +46 -3
  330. package/lib/shared-tree/schematizingTreeView.js.map +1 -1
  331. package/lib/shared-tree/sharedTree.d.ts +44 -21
  332. package/lib/shared-tree/sharedTree.d.ts.map +1 -1
  333. package/lib/shared-tree/sharedTree.js +40 -34
  334. package/lib/shared-tree/sharedTree.js.map +1 -1
  335. package/lib/shared-tree/transactionTypes.d.ts +105 -0
  336. package/lib/shared-tree/transactionTypes.d.ts.map +1 -0
  337. package/lib/shared-tree/transactionTypes.js +10 -0
  338. package/lib/shared-tree/transactionTypes.js.map +1 -0
  339. package/lib/shared-tree/treeApi.d.ts +1 -25
  340. package/lib/shared-tree/treeApi.d.ts.map +1 -1
  341. package/lib/shared-tree/treeApi.js +1 -5
  342. package/lib/shared-tree/treeApi.js.map +1 -1
  343. package/lib/shared-tree/treeCheckout.d.ts +4 -1
  344. package/lib/shared-tree/treeCheckout.d.ts.map +1 -1
  345. package/lib/shared-tree/treeCheckout.js +143 -24
  346. package/lib/shared-tree/treeCheckout.js.map +1 -1
  347. package/lib/shared-tree-core/sharedTreeCore.js +1 -1
  348. package/lib/shared-tree-core/sharedTreeCore.js.map +1 -1
  349. package/lib/simple-tree/api/index.d.ts +1 -0
  350. package/lib/simple-tree/api/index.d.ts.map +1 -1
  351. package/lib/simple-tree/api/index.js +1 -0
  352. package/lib/simple-tree/api/index.js.map +1 -1
  353. package/lib/simple-tree/api/jsonSchema.d.ts +6 -0
  354. package/lib/simple-tree/api/jsonSchema.d.ts.map +1 -1
  355. package/lib/simple-tree/api/jsonSchema.js.map +1 -1
  356. package/lib/simple-tree/api/schemaFactory.d.ts +21 -12
  357. package/lib/simple-tree/api/schemaFactory.d.ts.map +1 -1
  358. package/lib/simple-tree/api/schemaFactory.js +5 -2
  359. package/lib/simple-tree/api/schemaFactory.js.map +1 -1
  360. package/lib/simple-tree/api/schemaFactoryAlpha.d.ts +83 -0
  361. package/lib/simple-tree/api/schemaFactoryAlpha.d.ts.map +1 -0
  362. package/lib/simple-tree/api/schemaFactoryAlpha.js +86 -0
  363. package/lib/simple-tree/api/schemaFactoryAlpha.js.map +1 -0
  364. package/lib/simple-tree/api/simpleSchema.d.ts +5 -1
  365. package/lib/simple-tree/api/simpleSchema.d.ts.map +1 -1
  366. package/lib/simple-tree/api/simpleSchema.js.map +1 -1
  367. package/lib/simple-tree/api/simpleSchemaToJsonSchema.js +14 -11
  368. package/lib/simple-tree/api/simpleSchemaToJsonSchema.js.map +1 -1
  369. package/lib/simple-tree/api/testRecursiveDomain.d.ts +5 -5
  370. package/lib/simple-tree/api/tree.d.ts +60 -0
  371. package/lib/simple-tree/api/tree.d.ts.map +1 -1
  372. package/lib/simple-tree/api/tree.js.map +1 -1
  373. package/lib/simple-tree/api/treeNodeApi.js +1 -1
  374. package/lib/simple-tree/api/treeNodeApi.js.map +1 -1
  375. package/lib/simple-tree/api/viewSchemaToSimpleSchema.d.ts.map +1 -1
  376. package/lib/simple-tree/api/viewSchemaToSimpleSchema.js +12 -12
  377. package/lib/simple-tree/api/viewSchemaToSimpleSchema.js.map +1 -1
  378. package/lib/simple-tree/arrayNode.d.ts +2 -2
  379. package/lib/simple-tree/arrayNode.d.ts.map +1 -1
  380. package/lib/simple-tree/arrayNode.js +3 -2
  381. package/lib/simple-tree/arrayNode.js.map +1 -1
  382. package/lib/simple-tree/core/treeNodeSchema.d.ts +10 -6
  383. package/lib/simple-tree/core/treeNodeSchema.d.ts.map +1 -1
  384. package/lib/simple-tree/core/treeNodeSchema.js.map +1 -1
  385. package/lib/simple-tree/index.d.ts +2 -2
  386. package/lib/simple-tree/index.d.ts.map +1 -1
  387. package/lib/simple-tree/index.js +1 -1
  388. package/lib/simple-tree/index.js.map +1 -1
  389. package/lib/simple-tree/leafNodeSchema.d.ts +5 -5
  390. package/lib/simple-tree/leafNodeSchema.d.ts.map +1 -1
  391. package/lib/simple-tree/mapNode.d.ts +2 -2
  392. package/lib/simple-tree/mapNode.d.ts.map +1 -1
  393. package/lib/simple-tree/mapNode.js +2 -1
  394. package/lib/simple-tree/mapNode.js.map +1 -1
  395. package/lib/simple-tree/objectNode.d.ts +2 -2
  396. package/lib/simple-tree/objectNode.d.ts.map +1 -1
  397. package/lib/simple-tree/objectNode.js +2 -1
  398. package/lib/simple-tree/objectNode.js.map +1 -1
  399. package/lib/simple-tree/objectNodeTypes.d.ts +2 -2
  400. package/lib/simple-tree/objectNodeTypes.d.ts.map +1 -1
  401. package/lib/simple-tree/objectNodeTypes.js.map +1 -1
  402. package/lib/simple-tree/schemaTypes.d.ts +47 -1
  403. package/lib/simple-tree/schemaTypes.d.ts.map +1 -1
  404. package/lib/simple-tree/schemaTypes.js.map +1 -1
  405. package/lib/simple-tree/toMapTree.js +1 -1
  406. package/lib/simple-tree/toMapTree.js.map +1 -1
  407. package/lib/util/bTreeUtils.d.ts +10 -0
  408. package/lib/util/bTreeUtils.d.ts.map +1 -0
  409. package/lib/util/bTreeUtils.js +47 -0
  410. package/lib/util/bTreeUtils.js.map +1 -0
  411. package/lib/util/idAllocator.d.ts +0 -2
  412. package/lib/util/idAllocator.d.ts.map +1 -1
  413. package/lib/util/idAllocator.js +0 -2
  414. package/lib/util/idAllocator.js.map +1 -1
  415. package/lib/util/index.d.ts +3 -2
  416. package/lib/util/index.d.ts.map +1 -1
  417. package/lib/util/index.js +3 -2
  418. package/lib/util/index.js.map +1 -1
  419. package/lib/util/rangeMap.d.ts +95 -43
  420. package/lib/util/rangeMap.d.ts.map +1 -1
  421. package/lib/util/rangeMap.js +200 -144
  422. package/lib/util/rangeMap.js.map +1 -1
  423. package/lib/util/utils.d.ts +26 -2
  424. package/lib/util/utils.d.ts.map +1 -1
  425. package/lib/util/utils.js +15 -1
  426. package/lib/util/utils.js.map +1 -1
  427. package/package.json +24 -24
  428. package/src/core/index.ts +5 -2
  429. package/src/core/rebase/index.ts +5 -0
  430. package/src/core/rebase/types.ts +33 -5
  431. package/src/core/rebase/utils.ts +27 -0
  432. package/src/core/tree/delta.ts +21 -26
  433. package/src/core/tree/deltaUtil.ts +1 -16
  434. package/src/core/tree/index.ts +0 -2
  435. package/src/core/tree/visitDelta.ts +108 -97
  436. package/src/feature-libraries/default-schema/defaultEditBuilder.ts +14 -1
  437. package/src/feature-libraries/default-schema/defaultFieldKinds.ts +2 -2
  438. package/src/feature-libraries/deltaUtils.ts +13 -0
  439. package/src/feature-libraries/forest-summary/forestSummarizer.ts +1 -6
  440. package/src/feature-libraries/index.ts +0 -1
  441. package/src/feature-libraries/modular-schema/crossFieldQueries.ts +12 -13
  442. package/src/feature-libraries/modular-schema/fieldChangeHandler.ts +33 -9
  443. package/src/feature-libraries/modular-schema/genericFieldKind.ts +6 -4
  444. package/src/feature-libraries/modular-schema/index.ts +3 -0
  445. package/src/feature-libraries/modular-schema/modularChangeCodecs.ts +12 -11
  446. package/src/feature-libraries/modular-schema/modularChangeFamily.ts +254 -248
  447. package/src/feature-libraries/modular-schema/modularChangeTypes.ts +51 -26
  448. package/src/feature-libraries/optional-field/optionalField.ts +37 -8
  449. package/src/feature-libraries/sequence-field/moveEffectTable.ts +1 -1
  450. package/src/feature-libraries/sequence-field/rebase.ts +9 -3
  451. package/src/feature-libraries/sequence-field/sequenceFieldCodecV1.ts +1 -1
  452. package/src/feature-libraries/sequence-field/sequenceFieldCodecV2.ts +1 -1
  453. package/src/feature-libraries/sequence-field/sequenceFieldToDelta.ts +3 -4
  454. package/src/feature-libraries/sequence-field/utils.ts +54 -11
  455. package/src/feature-libraries/treeCursorUtils.ts +6 -1
  456. package/src/index.ts +45 -6
  457. package/src/packageVersion.ts +1 -1
  458. package/src/shared-tree/index.ts +16 -3
  459. package/src/shared-tree/schematizingTreeView.ts +91 -2
  460. package/src/shared-tree/sharedTree.ts +69 -44
  461. package/src/shared-tree/transactionTypes.ts +125 -0
  462. package/src/shared-tree/treeApi.ts +1 -28
  463. package/src/shared-tree/treeCheckout.ts +166 -25
  464. package/src/shared-tree-core/sharedTreeCore.ts +1 -1
  465. package/src/simple-tree/api/index.ts +1 -0
  466. package/src/simple-tree/api/jsonSchema.ts +7 -0
  467. package/src/simple-tree/api/schemaFactory.ts +33 -6
  468. package/src/simple-tree/api/schemaFactoryAlpha.ts +253 -0
  469. package/src/simple-tree/api/simpleSchema.ts +6 -1
  470. package/src/simple-tree/api/simpleSchemaToJsonSchema.ts +22 -12
  471. package/src/simple-tree/api/tree.ts +76 -4
  472. package/src/simple-tree/api/treeNodeApi.ts +1 -1
  473. package/src/simple-tree/api/viewSchemaToSimpleSchema.ts +19 -13
  474. package/src/simple-tree/arrayNode.ts +8 -2
  475. package/src/simple-tree/core/treeNodeSchema.ts +51 -7
  476. package/src/simple-tree/index.ts +3 -0
  477. package/src/simple-tree/mapNode.ts +7 -1
  478. package/src/simple-tree/objectNode.ts +7 -1
  479. package/src/simple-tree/objectNodeTypes.ts +4 -1
  480. package/src/simple-tree/schemaTypes.ts +50 -1
  481. package/src/simple-tree/toMapTree.ts +1 -1
  482. package/src/util/bTreeUtils.ts +60 -0
  483. package/src/util/idAllocator.ts +0 -2
  484. package/src/util/index.ts +5 -6
  485. package/src/util/rangeMap.ts +259 -184
  486. package/src/util/utils.ts +57 -4
  487. package/dist/feature-libraries/memoizedIdRangeAllocator.d.ts +0 -38
  488. package/dist/feature-libraries/memoizedIdRangeAllocator.d.ts.map +0 -1
  489. package/dist/feature-libraries/memoizedIdRangeAllocator.js +0 -74
  490. package/dist/feature-libraries/memoizedIdRangeAllocator.js.map +0 -1
  491. package/lib/feature-libraries/memoizedIdRangeAllocator.d.ts +0 -38
  492. package/lib/feature-libraries/memoizedIdRangeAllocator.d.ts.map +0 -1
  493. package/lib/feature-libraries/memoizedIdRangeAllocator.js +0 -71
  494. package/lib/feature-libraries/memoizedIdRangeAllocator.js.map +0 -1
  495. package/lib/package.json +0 -3
  496. package/src/feature-libraries/memoizedIdRangeAllocator.ts +0 -112
@@ -30,7 +30,6 @@ import {
30
30
  type RevisionTag,
31
31
  type TaggedChange,
32
32
  type UpPath,
33
- isEmptyFieldChanges,
34
33
  makeDetachedNodeId,
35
34
  mapCursorField,
36
35
  replaceAtomRevisions,
@@ -40,6 +39,9 @@ import {
40
39
  areEqualChangeAtomIdOpts,
41
40
  tagChange,
42
41
  makeAnonChange,
42
+ newChangeAtomIdRangeMap,
43
+ type DeltaDetachedNodeChanges,
44
+ type DeltaDetachedNodeRename,
43
45
  } from "../../core/index.js";
44
46
  import {
45
47
  type IdAllocationState,
@@ -51,6 +53,10 @@ import {
51
53
  idAllocatorFromState,
52
54
  type RangeQueryResult,
53
55
  getOrAddInMapLazy,
56
+ newTupleBTree,
57
+ mergeTupleBTrees,
58
+ type TupleBTree,
59
+ RangeMap,
54
60
  } from "../../util/index.js";
55
61
  import {
56
62
  type TreeChunk,
@@ -59,7 +65,6 @@ import {
59
65
  defaultChunkPolicy,
60
66
  } from "../chunked-forest/index.js";
61
67
  import { cursorForMapTreeNode, mapTreeFromCursor } from "../mapTreeCursor.js";
62
- import { MemoizedIdRangeAllocator } from "../memoizedIdRangeAllocator.js";
63
68
 
64
69
  import {
65
70
  type CrossFieldManager,
@@ -76,18 +81,19 @@ import {
76
81
  import { type FieldKindWithEditor, withEditor } from "./fieldKindWithEditor.js";
77
82
  import { convertGenericChange, genericFieldKind } from "./genericFieldKind.js";
78
83
  import type { GenericChangeset } from "./genericFieldKindTypes.js";
79
- import type {
80
- ChangeAtomIdBTree,
81
- CrossFieldKeyRange,
82
- CrossFieldKeyTable,
83
- FieldChange,
84
- FieldChangeMap,
85
- FieldChangeset,
86
- FieldId,
87
- ModularChangeset,
88
- NodeChangeset,
89
- NodeId,
90
- TupleBTree,
84
+ import {
85
+ type ChangeAtomIdBTree,
86
+ type CrossFieldKey,
87
+ type CrossFieldKeyRange,
88
+ type CrossFieldKeyTable,
89
+ type FieldChange,
90
+ type FieldChangeMap,
91
+ type FieldChangeset,
92
+ type FieldId,
93
+ type ModularChangeset,
94
+ newCrossFieldKeyTable,
95
+ type NodeChangeset,
96
+ type NodeId,
91
97
  } from "./modularChangeTypes.js";
92
98
  import type { IIdCompressor } from "@fluidframework/id-compressor";
93
99
 
@@ -253,7 +259,7 @@ export class ModularChangeFamily
253
259
  nodeChanges: newTupleBTree(),
254
260
  nodeToParent: newTupleBTree(),
255
261
  nodeAliases: newTupleBTree(),
256
- crossFieldKeys: newTupleBTree(),
262
+ crossFieldKeys: newCrossFieldKeyTable(),
257
263
  };
258
264
  } else if (hasConflicts(change1)) {
259
265
  return change2;
@@ -273,14 +279,14 @@ export class ModularChangeFamily
273
279
  // (since we assume that if two changesets use the same node ID they are referring to the same node),
274
280
  // therefore all collisions will be addressed when processing the intersection of the changesets.
275
281
  const composedNodeChanges: ChangeAtomIdBTree<NodeChangeset> = brand(
276
- mergeBTrees(change1.nodeChanges, change2.nodeChanges),
282
+ mergeTupleBTrees(change1.nodeChanges, change2.nodeChanges),
277
283
  );
278
284
 
279
285
  const composedNodeToParent: ChangeAtomIdBTree<FieldId> = brand(
280
- mergeBTrees(change1.nodeToParent, change2.nodeToParent),
286
+ mergeTupleBTrees(change1.nodeToParent, change2.nodeToParent),
281
287
  );
282
288
  const composedNodeAliases: ChangeAtomIdBTree<NodeId> = brand(
283
- mergeBTrees(change1.nodeAliases, change2.nodeAliases),
289
+ mergeTupleBTrees(change1.nodeAliases, change2.nodeAliases),
284
290
  );
285
291
 
286
292
  const crossFieldTable = newComposeTable(change1, change2, composedNodeToParent);
@@ -305,13 +311,16 @@ export class ModularChangeFamily
305
311
  );
306
312
 
307
313
  // Currently no field kinds require making changes to cross-field keys during composition, so we can just merge the two tables.
308
- const composedCrossFieldKeys = mergeBTrees(change1.crossFieldKeys, change2.crossFieldKeys);
314
+ const composedCrossFieldKeys = RangeMap.union(
315
+ change1.crossFieldKeys,
316
+ change2.crossFieldKeys,
317
+ );
309
318
  return {
310
319
  fieldChanges: composedFields,
311
320
  nodeChanges: composedNodeChanges,
312
321
  nodeToParent: composedNodeToParent,
313
322
  nodeAliases: composedNodeAliases,
314
- crossFieldKeys: brand(composedCrossFieldKeys),
323
+ crossFieldKeys: composedCrossFieldKeys,
315
324
  };
316
325
  }
317
326
 
@@ -649,8 +658,21 @@ export class ModularChangeFamily
649
658
  crossFieldTable: ComposeTable,
650
659
  revisionMetadata: RevisionMetadataSource,
651
660
  ): NodeChangeset {
661
+ // WARNING: this composition logic assumes that we never make compositions of the following form:
662
+ // change1: a changeset that impact the existence of a node
663
+ // change2: a node-exists constraint on that node.
664
+ // This is currently enforced by the fact that constraints which apply to the input context are included first in the composition.
665
+ // If that weren't the case, we would need to rebase the status of the constraint backward over the changes from change1.
652
666
  const nodeExistsConstraint = change1.nodeExistsConstraint ?? change2.nodeExistsConstraint;
653
667
 
668
+ // WARNING: this composition logic assumes that we never make compositions of the following form:
669
+ // change1: a node-exists-on-revert constraint on a node
670
+ // change2: a changeset that impacts the existence of that node
671
+ // This is currently enforced by the fact that constraints which apply to the revert are included last in the composition.
672
+ // If that weren't the case, we would need to rebase the status of the constraint forward over the changes from change2.
673
+ const nodeExistsConstraintOnRevert =
674
+ change1.nodeExistsConstraintOnRevert ?? change2.nodeExistsConstraintOnRevert;
675
+
654
676
  const composedFieldChanges = this.composeFieldMaps(
655
677
  change1.fieldChanges,
656
678
  change2.fieldChanges,
@@ -670,6 +692,10 @@ export class ModularChangeFamily
670
692
  composedNodeChange.nodeExistsConstraint = nodeExistsConstraint;
671
693
  }
672
694
 
695
+ if (nodeExistsConstraintOnRevert !== undefined) {
696
+ composedNodeChange.nodeExistsConstraintOnRevert = nodeExistsConstraintOnRevert;
697
+ }
698
+
673
699
  return composedNodeChange;
674
700
  }
675
701
 
@@ -778,7 +804,8 @@ export class ModularChangeFamily
778
804
  crossFieldKeys,
779
805
  maxId: genId.getMaxId(),
780
806
  revisions: revInfos,
781
- constraintViolationCount: change.change.constraintViolationCount,
807
+ constraintViolationCount: change.change.constraintViolationCountOnRevert,
808
+ constraintViolationCountOnRevert: change.change.constraintViolationCount,
782
809
  destroys,
783
810
  });
784
811
  }
@@ -835,6 +862,19 @@ export class ModularChangeFamily
835
862
  ): NodeChangeset {
836
863
  const inverse: NodeChangeset = {};
837
864
 
865
+ // If the node has a constraint, it should be inverted to a node-exist-on-revert constraint. This ensure that if
866
+ // the inverse is inverted again, the original input constraint will be restored.
867
+ if (change.nodeExistsConstraint !== undefined) {
868
+ inverse.nodeExistsConstraintOnRevert = change.nodeExistsConstraint;
869
+ }
870
+
871
+ // The node-exist-on-revert constraint of a node is the constraint that should apply when the a change is reverted.
872
+ // So, it should become the constraint in the inverse. If this constraint is violated when applying the inverse,
873
+ // it will be discarded.
874
+ if (change.nodeExistsConstraintOnRevert !== undefined) {
875
+ inverse.nodeExistsConstraint = change.nodeExistsConstraintOnRevert;
876
+ }
877
+
838
878
  if (change.fieldChanges !== undefined) {
839
879
  inverse.fieldChanges = this.invertFieldMap(
840
880
  change.fieldChanges,
@@ -872,14 +912,12 @@ export class ModularChangeFamily
872
912
  baseToRebasedNodeId: newTupleBTree(),
873
913
  rebasedFields: new Set(),
874
914
  rebasedNodeToParent: brand(change.nodeToParent.clone()),
875
- rebasedCrossFieldKeys: brand(change.crossFieldKeys.clone()),
915
+ rebasedCrossFieldKeys: change.crossFieldKeys.clone(),
876
916
  nodeIdPairs: [],
877
917
  affectedBaseFields: newTupleBTree(),
878
918
  fieldsWithUnattachedChild: new Set(),
879
919
  };
880
920
 
881
- const constraintState = newConstraintState(change.constraintViolationCount ?? 0);
882
-
883
921
  const getBaseRevisions = (): RevisionTag[] =>
884
922
  revisionInfoFromTaggedChange(over).map((info) => info.revision);
885
923
 
@@ -895,7 +933,6 @@ export class ModularChangeFamily
895
933
  crossFieldTable,
896
934
  rebasedNodes,
897
935
  genId,
898
- constraintState,
899
936
  rebaseMetadata,
900
937
  );
901
938
 
@@ -907,10 +944,16 @@ export class ModularChangeFamily
907
944
  genId,
908
945
  );
909
946
 
947
+ const constraintState = newConstraintState(change.constraintViolationCount ?? 0);
948
+ const revertConstraintState = newConstraintState(
949
+ change.constraintViolationCountOnRevert ?? 0,
950
+ );
910
951
  this.updateConstraintsForFields(
911
952
  rebasedFields,
912
953
  NodeAttachState.Attached,
954
+ NodeAttachState.Attached,
913
955
  constraintState,
956
+ revertConstraintState,
914
957
  rebasedNodes,
915
958
  );
916
959
 
@@ -923,6 +966,7 @@ export class ModularChangeFamily
923
966
  maxId: idState.maxId,
924
967
  revisions: change.revisions,
925
968
  constraintViolationCount: constraintState.violationCount,
969
+ constraintViolationCountOnRevert: revertConstraintState.violationCount,
926
970
  builds: change.builds,
927
971
  destroys: change.destroys,
928
972
  refreshers: change.refreshers,
@@ -937,7 +981,6 @@ export class ModularChangeFamily
937
981
  crossFieldTable: RebaseTable,
938
982
  rebasedNodes: ChangeAtomIdBTree<NodeChangeset>,
939
983
  genId: IdAllocator,
940
- constraintState: ConstraintState,
941
984
  metadata: RebaseRevisionMetadata,
942
985
  ): FieldChangeMap {
943
986
  const change = crossFieldTable.newChange;
@@ -960,7 +1003,6 @@ export class ModularChangeFamily
960
1003
  genId,
961
1004
  crossFieldTable,
962
1005
  metadata,
963
- constraintState,
964
1006
  );
965
1007
 
966
1008
  setInChangeAtomIdMap(rebasedNodes, newId, rebasedNode);
@@ -1336,7 +1378,6 @@ export class ModularChangeFamily
1336
1378
  genId: IdAllocator,
1337
1379
  crossFieldTable: RebaseTable,
1338
1380
  revisionMetadata: RebaseRevisionMetadata,
1339
- constraintState: ConstraintState,
1340
1381
  ): NodeChangeset {
1341
1382
  const change = nodeChangeFromId(crossFieldTable.newChange.nodeChanges, newId);
1342
1383
  const over = nodeChangeFromId(crossFieldTable.baseChange.nodeChanges, baseId);
@@ -1365,38 +1406,58 @@ export class ModularChangeFamily
1365
1406
  rebasedChange.nodeExistsConstraint = change.nodeExistsConstraint;
1366
1407
  }
1367
1408
 
1409
+ if (change?.nodeExistsConstraintOnRevert !== undefined) {
1410
+ rebasedChange.nodeExistsConstraintOnRevert = change.nodeExistsConstraintOnRevert;
1411
+ }
1412
+
1368
1413
  setInChangeAtomIdMap(crossFieldTable.baseToRebasedNodeId, baseId, newId);
1369
1414
  return rebasedChange;
1370
1415
  }
1371
1416
 
1372
1417
  private updateConstraintsForFields(
1373
1418
  fields: FieldChangeMap,
1374
- parentAttachState: NodeAttachState,
1419
+ parentInputAttachState: NodeAttachState,
1420
+ parentOutputAttachState: NodeAttachState,
1375
1421
  constraintState: ConstraintState,
1422
+ revertConstraintState: ConstraintState,
1376
1423
  nodes: ChangeAtomIdBTree<NodeChangeset>,
1377
1424
  ): void {
1378
1425
  for (const field of fields.values()) {
1379
1426
  const handler = getChangeHandler(this.fieldKinds, field.fieldKind);
1380
- for (const [nodeId, index] of handler.getNestedChanges(field.change)) {
1381
- const isDetached = index === undefined;
1382
- const attachState =
1383
- parentAttachState === NodeAttachState.Detached || isDetached
1427
+ for (const [nodeId, inputIndex, outputIndex] of handler.getNestedChanges(field.change)) {
1428
+ const isInputDetached = inputIndex === undefined;
1429
+ const inputAttachState =
1430
+ parentInputAttachState === NodeAttachState.Detached || isInputDetached
1384
1431
  ? NodeAttachState.Detached
1385
1432
  : NodeAttachState.Attached;
1386
- this.updateConstraintsForNode(nodeId, attachState, constraintState, nodes);
1433
+ const isOutputDetached = outputIndex === undefined;
1434
+ const outputAttachState =
1435
+ parentOutputAttachState === NodeAttachState.Detached || isOutputDetached
1436
+ ? NodeAttachState.Detached
1437
+ : NodeAttachState.Attached;
1438
+ this.updateConstraintsForNode(
1439
+ nodeId,
1440
+ inputAttachState,
1441
+ outputAttachState,
1442
+ nodes,
1443
+ constraintState,
1444
+ revertConstraintState,
1445
+ );
1387
1446
  }
1388
1447
  }
1389
1448
  }
1390
1449
 
1391
1450
  private updateConstraintsForNode(
1392
1451
  nodeId: NodeId,
1393
- attachState: NodeAttachState,
1394
- constraintState: ConstraintState,
1452
+ inputAttachState: NodeAttachState,
1453
+ outputAttachState: NodeAttachState,
1395
1454
  nodes: ChangeAtomIdBTree<NodeChangeset>,
1455
+ constraintState: ConstraintState,
1456
+ revertConstraintState: ConstraintState,
1396
1457
  ): void {
1397
1458
  const node = nodes.get([nodeId.revision, nodeId.localId]) ?? fail("Unknown node ID");
1398
1459
  if (node.nodeExistsConstraint !== undefined) {
1399
- const isNowViolated = attachState === NodeAttachState.Detached;
1460
+ const isNowViolated = inputAttachState === NodeAttachState.Detached;
1400
1461
  if (node.nodeExistsConstraint.violated !== isNowViolated) {
1401
1462
  node.nodeExistsConstraint = {
1402
1463
  ...node.nodeExistsConstraint,
@@ -1405,9 +1466,26 @@ export class ModularChangeFamily
1405
1466
  constraintState.violationCount += isNowViolated ? 1 : -1;
1406
1467
  }
1407
1468
  }
1469
+ if (node.nodeExistsConstraintOnRevert !== undefined) {
1470
+ const isNowViolated = outputAttachState === NodeAttachState.Detached;
1471
+ if (node.nodeExistsConstraintOnRevert.violated !== isNowViolated) {
1472
+ node.nodeExistsConstraintOnRevert = {
1473
+ ...node.nodeExistsConstraintOnRevert,
1474
+ violated: isNowViolated,
1475
+ };
1476
+ revertConstraintState.violationCount += isNowViolated ? 1 : -1;
1477
+ }
1478
+ }
1408
1479
 
1409
1480
  if (node.fieldChanges !== undefined) {
1410
- this.updateConstraintsForFields(node.fieldChanges, attachState, constraintState, nodes);
1481
+ this.updateConstraintsForFields(
1482
+ node.fieldChanges,
1483
+ inputAttachState,
1484
+ outputAttachState,
1485
+ constraintState,
1486
+ revertConstraintState,
1487
+ nodes,
1488
+ );
1411
1489
  }
1412
1490
  }
1413
1491
 
@@ -1599,8 +1677,8 @@ export class ModularChangeFamily
1599
1677
  const keys = getChangeHandler(this.fieldKinds, fieldChange.fieldKind).getCrossFieldKeys(
1600
1678
  fieldChange.change,
1601
1679
  );
1602
- for (const key of keys) {
1603
- table.set(key, { nodeId: parent, field: fieldKey });
1680
+ for (const { key, count } of keys) {
1681
+ table.set(key, count, { nodeId: parent, field: fieldKey });
1604
1682
  }
1605
1683
  }
1606
1684
  }
@@ -1660,7 +1738,7 @@ export class ModularChangeFamily
1660
1738
  }
1661
1739
 
1662
1740
  for (const keyRange of handler.getCrossFieldKeys(fieldChange.change)) {
1663
- const fields = getFieldsForCrossFieldKey(change, keyRange);
1741
+ const fields = getFieldsForCrossFieldKey(change, keyRange.key, keyRange.count);
1664
1742
  assert(
1665
1743
  fields.length === 1 &&
1666
1744
  fields[0] !== undefined &&
@@ -1680,15 +1758,16 @@ function replaceCrossFieldKeyTableRevisions(
1680
1758
  newRevision: RevisionTag | undefined,
1681
1759
  nodeAliases: ChangeAtomIdBTree<NodeId>,
1682
1760
  ): CrossFieldKeyTable {
1683
- const updated: CrossFieldKeyTable = newTupleBTree();
1684
- table.forEachPair(([target, revision, id, count], field) => {
1685
- const updatedKey: CrossFieldKeyRange = [
1686
- target,
1687
- replaceRevision(revision, oldRevisions, newRevision),
1688
- id,
1689
- count,
1690
- ];
1761
+ const updated: CrossFieldKeyTable = newCrossFieldKeyTable();
1762
+ for (const entry of table.entries()) {
1763
+ const key = entry.start;
1764
+ const updatedKey: CrossFieldKey = {
1765
+ target: key.target,
1766
+ revision: replaceRevision(key.revision, oldRevisions, newRevision),
1767
+ localId: key.localId,
1768
+ };
1691
1769
 
1770
+ const field = entry.value;
1692
1771
  const normalizedFieldId = normalizeFieldId(field, nodeAliases);
1693
1772
  const updatedNodeId =
1694
1773
  normalizedFieldId.nodeId !== undefined
@@ -1700,8 +1779,8 @@ function replaceCrossFieldKeyTableRevisions(
1700
1779
  nodeId: updatedNodeId,
1701
1780
  };
1702
1781
 
1703
- updated.set(updatedKey, updatedValue);
1704
- });
1782
+ updated.set(updatedKey, entry.length, updatedValue);
1783
+ }
1705
1784
 
1706
1785
  return updated;
1707
1786
  }
@@ -1748,15 +1827,19 @@ function composeBuildsDestroysAndRefreshers(
1748
1827
  // composition all the changes already reflected on the tree, but that is not something we
1749
1828
  // care to support at this time.
1750
1829
  const allBuilds: ChangeAtomIdBTree<TreeChunk> = brand(
1751
- mergeBTrees(change1.builds ?? newTupleBTree(), change2.builds ?? newTupleBTree(), true),
1830
+ mergeTupleBTrees(
1831
+ change1.builds ?? newTupleBTree(),
1832
+ change2.builds ?? newTupleBTree(),
1833
+ true,
1834
+ ),
1752
1835
  );
1753
1836
 
1754
1837
  const allDestroys: ChangeAtomIdBTree<number> = brand(
1755
- mergeBTrees(change1.destroys ?? newTupleBTree(), change2.destroys ?? newTupleBTree()),
1838
+ mergeTupleBTrees(change1.destroys ?? newTupleBTree(), change2.destroys ?? newTupleBTree()),
1756
1839
  );
1757
1840
 
1758
1841
  const allRefreshers: ChangeAtomIdBTree<TreeChunk> = brand(
1759
- mergeBTrees(
1842
+ mergeTupleBTrees(
1760
1843
  change1.refreshers ?? newTupleBTree(),
1761
1844
  change2.refreshers ?? newTupleBTree(),
1762
1845
  true,
@@ -1907,6 +1990,7 @@ export function updateRefreshers(
1907
1990
  maxId,
1908
1991
  revisions,
1909
1992
  constraintViolationCount,
1993
+ constraintViolationCountOnRevert,
1910
1994
  builds,
1911
1995
  destroys,
1912
1996
  } = change;
@@ -1920,6 +2004,7 @@ export function updateRefreshers(
1920
2004
  maxId: maxId as number,
1921
2005
  revisions,
1922
2006
  constraintViolationCount,
2007
+ constraintViolationCountOnRevert,
1923
2008
  builds,
1924
2009
  destroys,
1925
2010
  refreshers,
@@ -1927,6 +2012,8 @@ export function updateRefreshers(
1927
2012
  }
1928
2013
 
1929
2014
  /**
2015
+ * Converts a change into the delta format.
2016
+ *
1930
2017
  * @param change - The change to convert into a delta.
1931
2018
  * @param fieldKinds - The field kinds to delegate to.
1932
2019
  */
@@ -1935,20 +2022,28 @@ export function intoDelta(
1935
2022
  fieldKinds: ReadonlyMap<FieldKindIdentifier, FieldKindWithEditor>,
1936
2023
  ): DeltaRoot {
1937
2024
  const change = taggedChange.change;
1938
- const idAllocator = MemoizedIdRangeAllocator.fromNextId();
1939
2025
  const rootDelta: Mutable<DeltaRoot> = {};
2026
+ const global: DeltaDetachedNodeChanges[] = [];
2027
+ const rename: DeltaDetachedNodeRename[] = [];
1940
2028
 
1941
2029
  if (!hasConflicts(change)) {
1942
2030
  // If there are no constraint violations, then tree changes apply.
1943
2031
  const fieldDeltas = intoDeltaImpl(
1944
2032
  change.fieldChanges,
1945
2033
  change.nodeChanges,
1946
- idAllocator,
1947
2034
  fieldKinds,
2035
+ global,
2036
+ rename,
1948
2037
  );
1949
2038
  if (fieldDeltas.size > 0) {
1950
2039
  rootDelta.fields = fieldDeltas;
1951
2040
  }
2041
+ if (global.length > 0) {
2042
+ rootDelta.global = global;
2043
+ }
2044
+ if (rename.length > 0) {
2045
+ rootDelta.rename = rename;
2046
+ }
1952
2047
  }
1953
2048
 
1954
2049
  // Constraint violations should not prevent nodes from being built
@@ -1995,22 +2090,29 @@ function copyDetachedNodes(
1995
2090
  function intoDeltaImpl(
1996
2091
  change: FieldChangeMap,
1997
2092
  nodeChanges: ChangeAtomIdBTree<NodeChangeset>,
1998
- idAllocator: MemoizedIdRangeAllocator,
1999
2093
  fieldKinds: ReadonlyMap<FieldKindIdentifier, FieldKindWithEditor>,
2094
+ global: DeltaDetachedNodeChanges[],
2095
+ rename: DeltaDetachedNodeRename[],
2000
2096
  ): Map<FieldKey, DeltaFieldChanges> {
2001
2097
  const delta: Map<FieldKey, DeltaFieldChanges> = new Map();
2098
+
2002
2099
  for (const [field, fieldChange] of change) {
2003
- const deltaField = getChangeHandler(fieldKinds, fieldChange.fieldKind).intoDelta(
2100
+ const {
2101
+ local: fieldChanges,
2102
+ global: fieldGlobal,
2103
+ rename: fieldRename,
2104
+ } = getChangeHandler(fieldKinds, fieldChange.fieldKind).intoDelta(
2004
2105
  fieldChange.change,
2005
2106
  (childChange): DeltaFieldMap => {
2006
2107
  const nodeChange = nodeChangeFromId(nodeChanges, childChange);
2007
- return deltaFromNodeChange(nodeChange, nodeChanges, idAllocator, fieldKinds);
2108
+ return deltaFromNodeChange(nodeChange, nodeChanges, fieldKinds, global, rename);
2008
2109
  },
2009
- idAllocator,
2010
2110
  );
2011
- if (!isEmptyFieldChanges(deltaField)) {
2012
- delta.set(field, deltaField);
2111
+ if (fieldChanges !== undefined && fieldChanges.length > 0) {
2112
+ delta.set(field, fieldChanges);
2013
2113
  }
2114
+ fieldGlobal?.forEach((c) => global.push(c));
2115
+ fieldRename?.forEach((r) => rename.push(r));
2014
2116
  }
2015
2117
  return delta;
2016
2118
  }
@@ -2018,11 +2120,12 @@ function intoDeltaImpl(
2018
2120
  function deltaFromNodeChange(
2019
2121
  change: NodeChangeset,
2020
2122
  nodeChanges: ChangeAtomIdBTree<NodeChangeset>,
2021
- idAllocator: MemoizedIdRangeAllocator,
2022
2123
  fieldKinds: ReadonlyMap<FieldKindIdentifier, FieldKindWithEditor>,
2124
+ global: DeltaDetachedNodeChanges[],
2125
+ rename: DeltaDetachedNodeRename[],
2023
2126
  ): DeltaFieldMap {
2024
2127
  if (change.fieldChanges !== undefined) {
2025
- return intoDeltaImpl(change.fieldChanges, nodeChanges, idAllocator, fieldKinds);
2128
+ return intoDeltaImpl(change.fieldChanges, nodeChanges, fieldKinds, global, rename);
2026
2129
  }
2027
2130
  // TODO: update the API to allow undefined to be returned here
2028
2131
  return new Map();
@@ -2061,7 +2164,11 @@ export function rebaseRevisionMetadataFromInfo(
2061
2164
  }
2062
2165
 
2063
2166
  function isEmptyNodeChangeset(change: NodeChangeset): boolean {
2064
- return change.fieldChanges === undefined && change.nodeExistsConstraint === undefined;
2167
+ return (
2168
+ change.fieldChanges === undefined &&
2169
+ change.nodeExistsConstraint === undefined &&
2170
+ change.nodeExistsConstraintOnRevert === undefined
2171
+ );
2065
2172
  }
2066
2173
 
2067
2174
  export function getFieldKind(
@@ -2211,10 +2318,10 @@ interface ComposeFieldContext {
2211
2318
 
2212
2319
  function newCrossFieldTable<T>(): CrossFieldTable<T> {
2213
2320
  return {
2214
- srcTable: new Map(),
2215
- dstTable: new Map(),
2216
- srcDependents: new Map(),
2217
- dstDependents: new Map(),
2321
+ srcTable: newChangeAtomIdRangeMap(),
2322
+ dstTable: newChangeAtomIdRangeMap(),
2323
+ srcDependents: newChangeAtomIdRangeMap(),
2324
+ dstDependents: newChangeAtomIdRangeMap(),
2218
2325
  invalidatedFields: new Set(),
2219
2326
  };
2220
2327
  }
@@ -2272,7 +2379,7 @@ abstract class CrossFieldManagerI<T> implements CrossFieldManager {
2272
2379
  id: ChangesetLocalId,
2273
2380
  count: number,
2274
2381
  addDependency: boolean,
2275
- ): RangeQueryResult<unknown> {
2382
+ ): RangeQueryResult<ChangeAtomId, unknown> {
2276
2383
  if (addDependency) {
2277
2384
  // We assume that if there is already an entry for this ID it is because
2278
2385
  // a field handler has called compose on the same node multiple times.
@@ -2357,24 +2464,30 @@ class RebaseManager extends CrossFieldManagerI<FieldChange> {
2357
2464
  invalidateDependents: boolean,
2358
2465
  ): void {
2359
2466
  if (invalidateDependents && this.allowInval) {
2360
- const newFieldIds = getFieldsForCrossFieldKey(this.table.newChange, [
2361
- target,
2362
- revision,
2363
- id,
2467
+ const newFieldIds = getFieldsForCrossFieldKey(
2468
+ this.table.newChange,
2469
+ {
2470
+ target,
2471
+ revision,
2472
+ localId: id,
2473
+ },
2364
2474
  count,
2365
- ]);
2475
+ );
2366
2476
 
2367
2477
  assert(
2368
2478
  newFieldIds.length === 0,
2369
2479
  0x9c6 /* TODO: Modifying a cross-field key from the new changeset is currently unsupported */,
2370
2480
  );
2371
2481
 
2372
- const baseFieldIds = getFieldsForCrossFieldKey(this.table.baseChange, [
2373
- target,
2374
- revision,
2375
- id,
2482
+ const baseFieldIds = getFieldsForCrossFieldKey(
2483
+ this.table.baseChange,
2484
+ {
2485
+ target,
2486
+ revision,
2487
+ localId: id,
2488
+ },
2376
2489
  count,
2377
- ]);
2490
+ );
2378
2491
 
2379
2492
  assert(
2380
2493
  baseFieldIds.length > 0,
@@ -2402,11 +2515,8 @@ class RebaseManager extends CrossFieldManagerI<FieldChange> {
2402
2515
  id: ChangesetLocalId,
2403
2516
  count: number,
2404
2517
  ): void {
2405
- setInCrossFieldKeyTable(
2406
- this.table.rebasedCrossFieldKeys,
2407
- target,
2408
- revision,
2409
- id,
2518
+ this.table.rebasedCrossFieldKeys.set(
2519
+ { target, revision, localId: id },
2410
2520
  count,
2411
2521
  this.fieldId,
2412
2522
  );
@@ -2437,12 +2547,15 @@ class ComposeManager extends CrossFieldManagerI<FieldChange> {
2437
2547
  invalidateDependents: boolean,
2438
2548
  ): void {
2439
2549
  if (invalidateDependents && this.allowInval) {
2440
- const newFieldIds = getFieldsForCrossFieldKey(this.table.newChange, [
2441
- target,
2442
- revision,
2443
- id,
2550
+ const newFieldIds = getFieldsForCrossFieldKey(
2551
+ this.table.newChange,
2552
+ {
2553
+ target,
2554
+ revision,
2555
+ localId: id,
2556
+ },
2444
2557
  count,
2445
- ]);
2558
+ );
2446
2559
 
2447
2560
  if (newFieldIds.length > 0) {
2448
2561
  for (const newFieldId of newFieldIds) {
@@ -2452,12 +2565,15 @@ class ComposeManager extends CrossFieldManagerI<FieldChange> {
2452
2565
  );
2453
2566
  }
2454
2567
  } else {
2455
- const baseFieldIds = getFieldsForCrossFieldKey(this.table.baseChange, [
2456
- target,
2457
- revision,
2458
- id,
2568
+ const baseFieldIds = getFieldsForCrossFieldKey(
2569
+ this.table.baseChange,
2570
+ {
2571
+ target,
2572
+ revision,
2573
+ localId: id,
2574
+ },
2459
2575
  count,
2460
- ]);
2576
+ );
2461
2577
 
2462
2578
  assert(
2463
2579
  baseFieldIds.length > 0,
@@ -2504,6 +2620,7 @@ function makeModularChangeset(
2504
2620
  maxId: number;
2505
2621
  revisions?: readonly RevisionInfo[];
2506
2622
  constraintViolationCount?: number;
2623
+ constraintViolationCountOnRevert?: number;
2507
2624
  builds?: ChangeAtomIdBTree<TreeChunk>;
2508
2625
  destroys?: ChangeAtomIdBTree<number>;
2509
2626
  refreshers?: ChangeAtomIdBTree<TreeChunk>;
@@ -2528,6 +2645,12 @@ function makeModularChangeset(
2528
2645
  if (props.constraintViolationCount !== undefined && props.constraintViolationCount > 0) {
2529
2646
  changeset.constraintViolationCount = props.constraintViolationCount;
2530
2647
  }
2648
+ if (
2649
+ props.constraintViolationCountOnRevert !== undefined &&
2650
+ props.constraintViolationCountOnRevert > 0
2651
+ ) {
2652
+ changeset.constraintViolationCountOnRevert = props.constraintViolationCountOnRevert;
2653
+ }
2531
2654
  if (props.builds !== undefined && props.builds.size > 0) {
2532
2655
  changeset.builds = props.builds;
2533
2656
  }
@@ -2702,6 +2825,27 @@ export class ModularEditBuilder extends EditBuilder<ModularChangeset> {
2702
2825
  ),
2703
2826
  );
2704
2827
  }
2828
+
2829
+ public addNodeExistsConstraintOnRevert(path: UpPath, revision: RevisionTag): void {
2830
+ const nodeChange: NodeChangeset = {
2831
+ nodeExistsConstraintOnRevert: { violated: false },
2832
+ };
2833
+
2834
+ this.applyChange(
2835
+ tagChange(
2836
+ buildModularChangesetFromNode({
2837
+ path,
2838
+ nodeChange,
2839
+ nodeChanges: newTupleBTree(),
2840
+ nodeToParent: newTupleBTree(),
2841
+ crossFieldKeys: newCrossFieldKeyTable(),
2842
+ idAllocator: this.idAllocator,
2843
+ revision,
2844
+ }),
2845
+ revision,
2846
+ ),
2847
+ );
2848
+ }
2705
2849
  }
2706
2850
 
2707
2851
  function buildModularChangesetFromField(props: {
@@ -2729,8 +2873,8 @@ function buildModularChangesetFromField(props: {
2729
2873
  const fieldChanges: FieldChangeMap = new Map([[path.field, fieldChange]]);
2730
2874
 
2731
2875
  if (path.parent === undefined) {
2732
- for (const key of localCrossFieldKeys) {
2733
- crossFieldKeys.set(key, { nodeId: undefined, field: path.field });
2876
+ for (const { key, count } of localCrossFieldKeys) {
2877
+ crossFieldKeys.set(key, count, { nodeId: undefined, field: path.field });
2734
2878
  }
2735
2879
 
2736
2880
  if (childId !== undefined) {
@@ -2756,8 +2900,8 @@ function buildModularChangesetFromField(props: {
2756
2900
 
2757
2901
  const parentId: NodeId = { localId: brand(idAllocator.allocate()), revision };
2758
2902
 
2759
- for (const key of localCrossFieldKeys) {
2760
- crossFieldKeys.set(key, { nodeId: parentId, field: path.field });
2903
+ for (const { key, count } of localCrossFieldKeys) {
2904
+ crossFieldKeys.set(key, count, { nodeId: parentId, field: path.field });
2761
2905
  }
2762
2906
 
2763
2907
  if (childId !== undefined) {
@@ -2882,27 +3026,6 @@ function revisionInfoFromTaggedChange(
2882
3026
  return revInfos;
2883
3027
  }
2884
3028
 
2885
- function mergeBTrees<K extends readonly unknown[], V>(
2886
- tree1: TupleBTree<K, V> | undefined,
2887
- tree2: TupleBTree<K, V> | undefined,
2888
- preferLeft = true,
2889
- ): TupleBTree<K, V> {
2890
- if (tree1 === undefined) {
2891
- return tree2 !== undefined ? brand(tree2.clone()) : newTupleBTree<K, V>();
2892
- }
2893
-
2894
- const result: TupleBTree<K, V> = brand(tree1.clone());
2895
- if (tree2 === undefined) {
2896
- return result;
2897
- }
2898
-
2899
- for (const [key, value] of tree2.entries()) {
2900
- result.set(key, value, !preferLeft);
2901
- }
2902
-
2903
- return result;
2904
- }
2905
-
2906
3029
  function fieldChangeFromId(
2907
3030
  fields: FieldChangeMap,
2908
3031
  nodes: ChangeAtomIdBTree<NodeChangeset>,
@@ -2978,104 +3101,21 @@ export function getParentFieldId(changeset: ModularChangeset, nodeId: NodeId): F
2978
3101
  return normalizeFieldId(parentId, changeset.nodeAliases);
2979
3102
  }
2980
3103
 
2981
- export function getFieldsForCrossFieldKey(
3104
+ function getFieldsForCrossFieldKey(
2982
3105
  changeset: ModularChangeset,
2983
- [target, revision, id, count]: CrossFieldKeyRange,
2984
- ): FieldId[] {
2985
- let firstLocalId: number = id;
2986
- const lastLocalId = id + count - 1;
2987
-
2988
- const fields: FieldId[] = [];
2989
-
2990
- // eslint-disable-next-line no-constant-condition
2991
- while (true) {
2992
- const entry = getFirstIntersectingCrossFieldEntry(changeset.crossFieldKeys, [
2993
- target,
2994
- revision,
2995
- brand(firstLocalId),
2996
- count,
2997
- ]);
2998
-
2999
- if (entry === undefined) {
3000
- return fields;
3001
- }
3002
-
3003
- const [[_target, _revision, entryId, entryCount], fieldId] = entry;
3004
- fields.push(normalizeFieldId(fieldId, changeset.nodeAliases));
3005
-
3006
- const entryLastId = entryId + entryCount - 1;
3007
- if (entryLastId >= lastLocalId) {
3008
- return fields;
3009
- }
3010
-
3011
- firstLocalId = entryLastId + 1;
3012
- }
3013
- }
3014
-
3015
- function getFirstIntersectingCrossFieldEntry(
3016
- table: CrossFieldKeyTable,
3017
- [target, revision, id, count]: CrossFieldKeyRange,
3018
- ): [CrossFieldKeyRange, FieldId] | undefined {
3019
- const entry = table.nextLowerPair([target, revision, id, Number.POSITIVE_INFINITY]);
3020
- if (entry === undefined) {
3021
- return undefined;
3022
- }
3023
-
3024
- const [entryTarget, entryRevision, entryId, entryCount] = entry[0];
3025
- if (entryTarget !== target || entryRevision !== revision) {
3026
- return undefined;
3027
- }
3028
-
3029
- const lastQueryId = id + count - 1;
3030
- const entryLastId = entryId + entryCount - 1;
3031
- if (entryId > lastQueryId || entryLastId < id) {
3032
- return undefined;
3033
- }
3034
-
3035
- return entry;
3036
- }
3037
-
3038
- function setInCrossFieldKeyTable(
3039
- table: CrossFieldKeyTable,
3040
- target: CrossFieldTarget,
3041
- revision: RevisionTag | undefined,
3042
- id: ChangesetLocalId,
3106
+ key: CrossFieldKey,
3043
3107
  count: number,
3044
- value: FieldId,
3045
- ): void {
3046
- let entry = getFirstIntersectingCrossFieldEntry(table, [target, revision, id, count]);
3047
- const lastQueryId = id + count - 1;
3048
- while (entry !== undefined) {
3049
- const [entryKey, entryValue] = entry;
3050
- table.delete(entryKey);
3051
-
3052
- const [_target, _revision, entryId, entryCount] = entryKey;
3053
- if (entryId < id) {
3054
- table.set([target, revision, entryId, id - entryId], entryValue);
3055
- }
3056
-
3057
- const lastEntryId = entryId + entryCount - 1;
3058
- if (lastEntryId > lastQueryId) {
3059
- table.set(
3060
- [target, revision, brand(lastQueryId + 1), lastEntryId - lastQueryId],
3061
- entryValue,
3062
- );
3063
- break;
3064
- }
3065
-
3066
- const nextId: ChangesetLocalId = brand(lastEntryId + 1);
3067
- entry = getFirstIntersectingCrossFieldEntry(table, [
3068
- target,
3069
- revision,
3070
- nextId,
3071
- lastQueryId - nextId + 1,
3072
- ]);
3073
- }
3074
-
3075
- table.set([target, revision, id, count], value);
3108
+ ): FieldId[] {
3109
+ return changeset.crossFieldKeys
3110
+ .getAll(key, count)
3111
+ .map(({ value: fieldId }) => normalizeFieldId(fieldId, changeset.nodeAliases));
3076
3112
  }
3077
3113
 
3078
- function normalizeFieldId(fieldId: FieldId, nodeAliases: ChangeAtomIdBTree<NodeId>): FieldId {
3114
+ // This is only exported for use in test utilities.
3115
+ export function normalizeFieldId(
3116
+ fieldId: FieldId,
3117
+ nodeAliases: ChangeAtomIdBTree<NodeId>,
3118
+ ): FieldId {
3079
3119
  return fieldId.nodeId !== undefined
3080
3120
  ? { ...fieldId, nodeId: normalizeNodeId(fieldId.nodeId, nodeAliases) }
3081
3121
  : fieldId;
@@ -3102,40 +3142,6 @@ function hasConflicts(change: ModularChangeset): boolean {
3102
3142
  return (change.constraintViolationCount ?? 0) > 0;
3103
3143
  }
3104
3144
 
3105
- export function newCrossFieldKeyTable(): CrossFieldKeyTable {
3106
- return newTupleBTree();
3107
- }
3108
-
3109
- export function newTupleBTree<K extends readonly unknown[], V>(
3110
- entries?: [K, V][],
3111
- ): TupleBTree<K, V> {
3112
- return brand(new BTree<K, V>(entries, compareTuples));
3113
- }
3114
-
3115
- // This assumes that the arrays are the same length.
3116
- function compareTuples(arrayA: readonly unknown[], arrayB: readonly unknown[]): number {
3117
- for (let i = 0; i < arrayA.length; i++) {
3118
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
3119
- const a = arrayA[i] as any;
3120
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
3121
- const b = arrayB[i] as any;
3122
-
3123
- // Less-than and greater-than always return false if either value is undefined,
3124
- // so we handle undefined separately, treating it as less than all other values.
3125
- if (a === undefined && b !== undefined) {
3126
- return -1;
3127
- } else if (b === undefined && a !== undefined) {
3128
- return 1;
3129
- } else if (a < b) {
3130
- return -1;
3131
- } else if (a > b) {
3132
- return 1;
3133
- }
3134
- }
3135
-
3136
- return 0;
3137
- }
3138
-
3139
3145
  interface ModularChangesetContent {
3140
3146
  fieldChanges: FieldChangeMap;
3141
3147
  nodeChanges: ChangeAtomIdBTree<NodeChangeset>;