@fluidframework/tree 2.80.0 → 2.81.0-374083

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 (914) hide show
  1. package/api-report/tree.alpha.api.md +43 -7
  2. package/dist/alpha.d.ts +5 -0
  3. package/dist/core/change-family/changeFamily.d.ts +4 -1
  4. package/dist/core/change-family/changeFamily.d.ts.map +1 -1
  5. package/dist/core/change-family/changeFamily.js.map +1 -1
  6. package/dist/core/change-family/index.d.ts +1 -1
  7. package/dist/core/change-family/index.d.ts.map +1 -1
  8. package/dist/core/change-family/index.js.map +1 -1
  9. package/dist/core/index.d.ts +3 -3
  10. package/dist/core/index.d.ts.map +1 -1
  11. package/dist/core/index.js +6 -4
  12. package/dist/core/index.js.map +1 -1
  13. package/dist/core/rebase/changeRebaser.d.ts +6 -1
  14. package/dist/core/rebase/changeRebaser.d.ts.map +1 -1
  15. package/dist/core/rebase/changeRebaser.js.map +1 -1
  16. package/dist/core/rebase/index.d.ts +1 -1
  17. package/dist/core/rebase/index.d.ts.map +1 -1
  18. package/dist/core/rebase/index.js +2 -1
  19. package/dist/core/rebase/index.js.map +1 -1
  20. package/dist/core/rebase/types.d.ts +46 -8
  21. package/dist/core/rebase/types.d.ts.map +1 -1
  22. package/dist/core/rebase/types.js +5 -1
  23. package/dist/core/rebase/types.js.map +1 -1
  24. package/dist/core/rebase/utils.d.ts.map +1 -1
  25. package/dist/core/rebase/utils.js +30 -8
  26. package/dist/core/rebase/utils.js.map +1 -1
  27. package/dist/core/tree/anchorSet.js +1 -0
  28. package/dist/core/tree/anchorSet.js.map +1 -1
  29. package/dist/core/tree/detachedFieldIndex.d.ts +6 -0
  30. package/dist/core/tree/detachedFieldIndex.d.ts.map +1 -1
  31. package/dist/core/tree/detachedFieldIndex.js +9 -0
  32. package/dist/core/tree/detachedFieldIndex.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 +4 -3
  36. package/dist/core/tree/index.js.map +1 -1
  37. package/dist/core/tree/pathTree.d.ts +11 -3
  38. package/dist/core/tree/pathTree.d.ts.map +1 -1
  39. package/dist/core/tree/pathTree.js +14 -2
  40. package/dist/core/tree/pathTree.js.map +1 -1
  41. package/dist/core/tree/visitDelta.d.ts.map +1 -1
  42. package/dist/core/tree/visitDelta.js +3 -2
  43. package/dist/core/tree/visitDelta.js.map +1 -1
  44. package/dist/core/tree/visitorUtils.d.ts.map +1 -1
  45. package/dist/core/tree/visitorUtils.js +58 -18
  46. package/dist/core/tree/visitorUtils.js.map +1 -1
  47. package/dist/feature-libraries/changeAtomIdBTree.d.ts +10 -4
  48. package/dist/feature-libraries/changeAtomIdBTree.d.ts.map +1 -1
  49. package/dist/feature-libraries/changeAtomIdBTree.js +16 -2
  50. package/dist/feature-libraries/changeAtomIdBTree.js.map +1 -1
  51. package/dist/feature-libraries/chunked-forest/basicChunk.d.ts.map +1 -1
  52. package/dist/feature-libraries/chunked-forest/basicChunk.js +7 -0
  53. package/dist/feature-libraries/chunked-forest/basicChunk.js.map +1 -1
  54. package/dist/feature-libraries/chunked-forest/chunkTree.d.ts.map +1 -1
  55. package/dist/feature-libraries/chunked-forest/chunkTree.js +4 -1
  56. package/dist/feature-libraries/chunked-forest/chunkTree.js.map +1 -1
  57. package/dist/feature-libraries/chunked-forest/chunkedForest.d.ts.map +1 -1
  58. package/dist/feature-libraries/chunked-forest/chunkedForest.js +3 -1
  59. package/dist/feature-libraries/chunked-forest/chunkedForest.js.map +1 -1
  60. package/dist/feature-libraries/chunked-forest/codec/compressedEncode.js +1 -0
  61. package/dist/feature-libraries/chunked-forest/codec/compressedEncode.js.map +1 -1
  62. package/dist/feature-libraries/default-schema/defaultEditBuilder.d.ts +93 -44
  63. package/dist/feature-libraries/default-schema/defaultEditBuilder.d.ts.map +1 -1
  64. package/dist/feature-libraries/default-schema/defaultEditBuilder.js +238 -69
  65. package/dist/feature-libraries/default-schema/defaultEditBuilder.js.map +1 -1
  66. package/dist/feature-libraries/default-schema/defaultFieldKinds.d.ts +1 -1
  67. package/dist/feature-libraries/default-schema/defaultFieldKinds.d.ts.map +1 -1
  68. package/dist/feature-libraries/default-schema/defaultFieldKinds.js +11 -2
  69. package/dist/feature-libraries/default-schema/defaultFieldKinds.js.map +1 -1
  70. package/dist/feature-libraries/default-schema/index.d.ts +2 -1
  71. package/dist/feature-libraries/default-schema/index.d.ts.map +1 -1
  72. package/dist/feature-libraries/default-schema/index.js +5 -2
  73. package/dist/feature-libraries/default-schema/index.js.map +1 -1
  74. package/dist/feature-libraries/default-schema/locationBasedEditBuilder.d.ts +38 -0
  75. package/dist/feature-libraries/default-schema/locationBasedEditBuilder.d.ts.map +1 -0
  76. package/dist/feature-libraries/default-schema/locationBasedEditBuilder.js +132 -0
  77. package/dist/feature-libraries/default-schema/locationBasedEditBuilder.js.map +1 -0
  78. package/dist/feature-libraries/default-schema/mappedEditBuilder.d.ts +7 -6
  79. package/dist/feature-libraries/default-schema/mappedEditBuilder.d.ts.map +1 -1
  80. package/dist/feature-libraries/default-schema/mappedEditBuilder.js +15 -0
  81. package/dist/feature-libraries/default-schema/mappedEditBuilder.js.map +1 -1
  82. package/dist/feature-libraries/deltaUtils.d.ts +1 -0
  83. package/dist/feature-libraries/deltaUtils.d.ts.map +1 -1
  84. package/dist/feature-libraries/deltaUtils.js +6 -1
  85. package/dist/feature-libraries/deltaUtils.js.map +1 -1
  86. package/dist/feature-libraries/flex-tree/context.d.ts +9 -0
  87. package/dist/feature-libraries/flex-tree/context.d.ts.map +1 -1
  88. package/dist/feature-libraries/flex-tree/context.js +6 -0
  89. package/dist/feature-libraries/flex-tree/context.js.map +1 -1
  90. package/dist/feature-libraries/flex-tree/flexTreeTypes.d.ts +6 -6
  91. package/dist/feature-libraries/flex-tree/flexTreeTypes.d.ts.map +1 -1
  92. package/dist/feature-libraries/flex-tree/flexTreeTypes.js.map +1 -1
  93. package/dist/feature-libraries/flex-tree/lazyField.d.ts +8 -7
  94. package/dist/feature-libraries/flex-tree/lazyField.d.ts.map +1 -1
  95. package/dist/feature-libraries/flex-tree/lazyField.js +40 -9
  96. package/dist/feature-libraries/flex-tree/lazyField.js.map +1 -1
  97. package/dist/feature-libraries/forest-summary/forestSummarizer.d.ts.map +1 -1
  98. package/dist/feature-libraries/forest-summary/forestSummarizer.js +3 -1
  99. package/dist/feature-libraries/forest-summary/forestSummarizer.js.map +1 -1
  100. package/dist/feature-libraries/index.d.ts +3 -3
  101. package/dist/feature-libraries/index.d.ts.map +1 -1
  102. package/dist/feature-libraries/index.js +8 -3
  103. package/dist/feature-libraries/index.js.map +1 -1
  104. package/dist/feature-libraries/mapTreeCursor.d.ts.map +1 -1
  105. package/dist/feature-libraries/mapTreeCursor.js +1 -0
  106. package/dist/feature-libraries/mapTreeCursor.js.map +1 -1
  107. package/dist/feature-libraries/mitigatedChangeFamily.d.ts.map +1 -1
  108. package/dist/feature-libraries/mitigatedChangeFamily.js +2 -2
  109. package/dist/feature-libraries/mitigatedChangeFamily.js.map +1 -1
  110. package/dist/feature-libraries/modular-schema/crossFieldQueries.d.ts +97 -21
  111. package/dist/feature-libraries/modular-schema/crossFieldQueries.d.ts.map +1 -1
  112. package/dist/feature-libraries/modular-schema/crossFieldQueries.js +4 -7
  113. package/dist/feature-libraries/modular-schema/crossFieldQueries.js.map +1 -1
  114. package/dist/feature-libraries/modular-schema/fieldChangeHandler.d.ts +20 -51
  115. package/dist/feature-libraries/modular-schema/fieldChangeHandler.d.ts.map +1 -1
  116. package/dist/feature-libraries/modular-schema/fieldChangeHandler.js.map +1 -1
  117. package/dist/feature-libraries/modular-schema/genericFieldKind.d.ts.map +1 -1
  118. package/dist/feature-libraries/modular-schema/genericFieldKind.js +3 -9
  119. package/dist/feature-libraries/modular-schema/genericFieldKind.js.map +1 -1
  120. package/dist/feature-libraries/modular-schema/index.d.ts +4 -4
  121. package/dist/feature-libraries/modular-schema/index.d.ts.map +1 -1
  122. package/dist/feature-libraries/modular-schema/index.js +2 -2
  123. package/dist/feature-libraries/modular-schema/index.js.map +1 -1
  124. package/dist/feature-libraries/modular-schema/modularChangeCodecV1.d.ts +11 -28
  125. package/dist/feature-libraries/modular-schema/modularChangeCodecV1.d.ts.map +1 -1
  126. package/dist/feature-libraries/modular-schema/modularChangeCodecV1.js +255 -161
  127. package/dist/feature-libraries/modular-schema/modularChangeCodecV1.js.map +1 -1
  128. package/dist/feature-libraries/modular-schema/modularChangeCodecV3.d.ts +15 -0
  129. package/dist/feature-libraries/modular-schema/modularChangeCodecV3.d.ts.map +1 -0
  130. package/dist/feature-libraries/modular-schema/modularChangeCodecV3.js +393 -0
  131. package/dist/feature-libraries/modular-schema/modularChangeCodecV3.js.map +1 -0
  132. package/dist/feature-libraries/modular-schema/modularChangeCodecs.d.ts.map +1 -1
  133. package/dist/feature-libraries/modular-schema/modularChangeCodecs.js +8 -1
  134. package/dist/feature-libraries/modular-schema/modularChangeCodecs.js.map +1 -1
  135. package/dist/feature-libraries/modular-schema/modularChangeFamily.d.ts +48 -20
  136. package/dist/feature-libraries/modular-schema/modularChangeFamily.d.ts.map +1 -1
  137. package/dist/feature-libraries/modular-schema/modularChangeFamily.js +1350 -476
  138. package/dist/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
  139. package/dist/feature-libraries/modular-schema/modularChangeFormatV1.d.ts.map +1 -1
  140. package/dist/feature-libraries/modular-schema/modularChangeFormatV1.js.map +1 -1
  141. package/dist/feature-libraries/modular-schema/modularChangeFormatV3.d.ts +146 -0
  142. package/dist/feature-libraries/modular-schema/modularChangeFormatV3.d.ts.map +1 -0
  143. package/dist/feature-libraries/modular-schema/modularChangeFormatV3.js +32 -0
  144. package/dist/feature-libraries/modular-schema/modularChangeFormatV3.js.map +1 -0
  145. package/dist/feature-libraries/modular-schema/modularChangeTypes.d.ts +47 -11
  146. package/dist/feature-libraries/modular-schema/modularChangeTypes.d.ts.map +1 -1
  147. package/dist/feature-libraries/modular-schema/modularChangeTypes.js +3 -3
  148. package/dist/feature-libraries/modular-schema/modularChangeTypes.js.map +1 -1
  149. package/dist/feature-libraries/object-forest/objectForest.d.ts.map +1 -1
  150. package/dist/feature-libraries/object-forest/objectForest.js +3 -1
  151. package/dist/feature-libraries/object-forest/objectForest.js.map +1 -1
  152. package/dist/feature-libraries/optional-field/index.d.ts +2 -2
  153. package/dist/feature-libraries/optional-field/index.d.ts.map +1 -1
  154. package/dist/feature-libraries/optional-field/index.js +1 -2
  155. package/dist/feature-libraries/optional-field/index.js.map +1 -1
  156. package/dist/feature-libraries/optional-field/optionalField.d.ts +5 -26
  157. package/dist/feature-libraries/optional-field/optionalField.d.ts.map +1 -1
  158. package/dist/feature-libraries/optional-field/optionalField.js +221 -443
  159. package/dist/feature-libraries/optional-field/optionalField.js.map +1 -1
  160. package/dist/feature-libraries/optional-field/optionalFieldChangeFormatV3.d.ts +23 -0
  161. package/dist/feature-libraries/optional-field/optionalFieldChangeFormatV3.d.ts.map +1 -0
  162. package/dist/feature-libraries/optional-field/optionalFieldChangeFormatV3.js +31 -0
  163. package/dist/feature-libraries/optional-field/optionalFieldChangeFormatV3.js.map +1 -0
  164. package/dist/feature-libraries/optional-field/optionalFieldChangeTypes.d.ts +24 -33
  165. package/dist/feature-libraries/optional-field/optionalFieldChangeTypes.d.ts.map +1 -1
  166. package/dist/feature-libraries/optional-field/optionalFieldChangeTypes.js.map +1 -1
  167. package/dist/feature-libraries/optional-field/optionalFieldCodecV2.d.ts +1 -1
  168. package/dist/feature-libraries/optional-field/optionalFieldCodecV2.d.ts.map +1 -1
  169. package/dist/feature-libraries/optional-field/optionalFieldCodecV2.js +57 -28
  170. package/dist/feature-libraries/optional-field/optionalFieldCodecV2.js.map +1 -1
  171. package/dist/feature-libraries/optional-field/optionalFieldCodecV3.d.ts +12 -0
  172. package/dist/feature-libraries/optional-field/optionalFieldCodecV3.d.ts.map +1 -0
  173. package/dist/feature-libraries/optional-field/optionalFieldCodecV3.js +57 -0
  174. package/dist/feature-libraries/optional-field/optionalFieldCodecV3.js.map +1 -0
  175. package/dist/feature-libraries/optional-field/optionalFieldCodecs.d.ts.map +1 -1
  176. package/dist/feature-libraries/optional-field/optionalFieldCodecs.js +5 -1
  177. package/dist/feature-libraries/optional-field/optionalFieldCodecs.js.map +1 -1
  178. package/dist/feature-libraries/sequence-field/compose.d.ts +6 -7
  179. package/dist/feature-libraries/sequence-field/compose.d.ts.map +1 -1
  180. package/dist/feature-libraries/sequence-field/compose.js +83 -259
  181. package/dist/feature-libraries/sequence-field/compose.js.map +1 -1
  182. package/dist/feature-libraries/sequence-field/helperTypes.d.ts +14 -10
  183. package/dist/feature-libraries/sequence-field/helperTypes.d.ts.map +1 -1
  184. package/dist/feature-libraries/sequence-field/helperTypes.js.map +1 -1
  185. package/dist/feature-libraries/sequence-field/index.d.ts +2 -3
  186. package/dist/feature-libraries/sequence-field/index.d.ts.map +1 -1
  187. package/dist/feature-libraries/sequence-field/index.js +1 -3
  188. package/dist/feature-libraries/sequence-field/index.js.map +1 -1
  189. package/dist/feature-libraries/sequence-field/invert.d.ts +3 -3
  190. package/dist/feature-libraries/sequence-field/invert.d.ts.map +1 -1
  191. package/dist/feature-libraries/sequence-field/invert.js +65 -167
  192. package/dist/feature-libraries/sequence-field/invert.js.map +1 -1
  193. package/dist/feature-libraries/sequence-field/markQueue.d.ts +2 -2
  194. package/dist/feature-libraries/sequence-field/markQueue.d.ts.map +1 -1
  195. package/dist/feature-libraries/sequence-field/markQueue.js.map +1 -1
  196. package/dist/feature-libraries/sequence-field/moveEffectTable.d.ts +4 -56
  197. package/dist/feature-libraries/sequence-field/moveEffectTable.d.ts.map +1 -1
  198. package/dist/feature-libraries/sequence-field/moveEffectTable.js +7 -90
  199. package/dist/feature-libraries/sequence-field/moveEffectTable.js.map +1 -1
  200. package/dist/feature-libraries/sequence-field/rebase.d.ts +3 -3
  201. package/dist/feature-libraries/sequence-field/rebase.d.ts.map +1 -1
  202. package/dist/feature-libraries/sequence-field/rebase.js +107 -114
  203. package/dist/feature-libraries/sequence-field/rebase.js.map +1 -1
  204. package/dist/feature-libraries/sequence-field/replaceRevisions.d.ts.map +1 -1
  205. package/dist/feature-libraries/sequence-field/replaceRevisions.js +18 -31
  206. package/dist/feature-libraries/sequence-field/replaceRevisions.js.map +1 -1
  207. package/dist/feature-libraries/sequence-field/sequenceFieldChangeHandler.d.ts.map +1 -1
  208. package/dist/feature-libraries/sequence-field/sequenceFieldChangeHandler.js +0 -2
  209. package/dist/feature-libraries/sequence-field/sequenceFieldChangeHandler.js.map +1 -1
  210. package/dist/feature-libraries/sequence-field/sequenceFieldCodecV2.d.ts +22 -4
  211. package/dist/feature-libraries/sequence-field/sequenceFieldCodecV2.d.ts.map +1 -1
  212. package/dist/feature-libraries/sequence-field/sequenceFieldCodecV2.js +365 -187
  213. package/dist/feature-libraries/sequence-field/sequenceFieldCodecV2.js.map +1 -1
  214. package/dist/feature-libraries/sequence-field/sequenceFieldCodecV3.d.ts.map +1 -1
  215. package/dist/feature-libraries/sequence-field/sequenceFieldCodecV3.js +20 -62
  216. package/dist/feature-libraries/sequence-field/sequenceFieldCodecV3.js.map +1 -1
  217. package/dist/feature-libraries/sequence-field/sequenceFieldEditor.d.ts +2 -2
  218. package/dist/feature-libraries/sequence-field/sequenceFieldEditor.d.ts.map +1 -1
  219. package/dist/feature-libraries/sequence-field/sequenceFieldEditor.js +10 -10
  220. package/dist/feature-libraries/sequence-field/sequenceFieldEditor.js.map +1 -1
  221. package/dist/feature-libraries/sequence-field/sequenceFieldToDelta.d.ts +3 -2
  222. package/dist/feature-libraries/sequence-field/sequenceFieldToDelta.d.ts.map +1 -1
  223. package/dist/feature-libraries/sequence-field/sequenceFieldToDelta.js +14 -109
  224. package/dist/feature-libraries/sequence-field/sequenceFieldToDelta.js.map +1 -1
  225. package/dist/feature-libraries/sequence-field/types.d.ts +30 -59
  226. package/dist/feature-libraries/sequence-field/types.d.ts.map +1 -1
  227. package/dist/feature-libraries/sequence-field/types.js.map +1 -1
  228. package/dist/feature-libraries/sequence-field/utils.d.ts +15 -24
  229. package/dist/feature-libraries/sequence-field/utils.d.ts.map +1 -1
  230. package/dist/feature-libraries/sequence-field/utils.js +116 -305
  231. package/dist/feature-libraries/sequence-field/utils.js.map +1 -1
  232. package/dist/index.d.ts +3 -2
  233. package/dist/index.d.ts.map +1 -1
  234. package/dist/index.js +4 -1
  235. package/dist/index.js.map +1 -1
  236. package/dist/packageVersion.d.ts +1 -1
  237. package/dist/packageVersion.d.ts.map +1 -1
  238. package/dist/packageVersion.js +1 -1
  239. package/dist/packageVersion.js.map +1 -1
  240. package/dist/shared-tree/index.d.ts +1 -1
  241. package/dist/shared-tree/index.d.ts.map +1 -1
  242. package/dist/shared-tree/index.js.map +1 -1
  243. package/dist/shared-tree/schematizeTree.d.ts +4 -4
  244. package/dist/shared-tree/schematizeTree.d.ts.map +1 -1
  245. package/dist/shared-tree/schematizeTree.js +2 -1
  246. package/dist/shared-tree/schematizeTree.js.map +1 -1
  247. package/dist/shared-tree/schematizingTreeView.d.ts +1 -5
  248. package/dist/shared-tree/schematizingTreeView.d.ts.map +1 -1
  249. package/dist/shared-tree/schematizingTreeView.js +38 -35
  250. package/dist/shared-tree/schematizingTreeView.js.map +1 -1
  251. package/dist/shared-tree/sharedTree.d.ts +9 -3
  252. package/dist/shared-tree/sharedTree.d.ts.map +1 -1
  253. package/dist/shared-tree/sharedTree.js +11 -0
  254. package/dist/shared-tree/sharedTree.js.map +1 -1
  255. package/dist/shared-tree/sharedTreeChangeCodecs.d.ts +1 -1
  256. package/dist/shared-tree/sharedTreeChangeCodecs.d.ts.map +1 -1
  257. package/dist/shared-tree/sharedTreeChangeCodecs.js +1 -0
  258. package/dist/shared-tree/sharedTreeChangeCodecs.js.map +1 -1
  259. package/dist/shared-tree/sharedTreeChangeEnricher.d.ts.map +1 -1
  260. package/dist/shared-tree/sharedTreeChangeEnricher.js +1 -1
  261. package/dist/shared-tree/sharedTreeChangeEnricher.js.map +1 -1
  262. package/dist/shared-tree/sharedTreeChangeFamily.d.ts +5 -5
  263. package/dist/shared-tree/sharedTreeChangeFamily.d.ts.map +1 -1
  264. package/dist/shared-tree/sharedTreeChangeFamily.js +10 -4
  265. package/dist/shared-tree/sharedTreeChangeFamily.js.map +1 -1
  266. package/dist/shared-tree/sharedTreeEditBuilder.d.ts +16 -6
  267. package/dist/shared-tree/sharedTreeEditBuilder.d.ts.map +1 -1
  268. package/dist/shared-tree/sharedTreeEditBuilder.js +14 -7
  269. package/dist/shared-tree/sharedTreeEditBuilder.js.map +1 -1
  270. package/dist/shared-tree/treeCheckout.d.ts +9 -10
  271. package/dist/shared-tree/treeCheckout.d.ts.map +1 -1
  272. package/dist/shared-tree/treeCheckout.js +63 -8
  273. package/dist/shared-tree/treeCheckout.js.map +1 -1
  274. package/dist/shared-tree-core/branch.d.ts +3 -2
  275. package/dist/shared-tree-core/branch.d.ts.map +1 -1
  276. package/dist/shared-tree-core/branch.js +9 -4
  277. package/dist/shared-tree-core/branch.js.map +1 -1
  278. package/dist/shared-tree-core/editManager.d.ts +2 -2
  279. package/dist/shared-tree-core/editManager.d.ts.map +1 -1
  280. package/dist/shared-tree-core/editManager.js +20 -14
  281. package/dist/shared-tree-core/editManager.js.map +1 -1
  282. package/dist/shared-tree-core/editManagerCodecs.d.ts +4 -0
  283. package/dist/shared-tree-core/editManagerCodecs.d.ts.map +1 -1
  284. package/dist/shared-tree-core/editManagerCodecs.js +10 -2
  285. package/dist/shared-tree-core/editManagerCodecs.js.map +1 -1
  286. package/dist/shared-tree-core/editManagerFormatCommons.d.ts +1 -0
  287. package/dist/shared-tree-core/editManagerFormatCommons.d.ts.map +1 -1
  288. package/dist/shared-tree-core/editManagerFormatCommons.js +6 -0
  289. package/dist/shared-tree-core/editManagerFormatCommons.js.map +1 -1
  290. package/dist/shared-tree-core/editManagerFormatV1toV4.d.ts +2 -2
  291. package/dist/shared-tree-core/editManagerFormatV1toV4.d.ts.map +1 -1
  292. package/dist/shared-tree-core/editManagerFormatV1toV4.js +1 -0
  293. package/dist/shared-tree-core/editManagerFormatV1toV4.js.map +1 -1
  294. package/dist/shared-tree-core/index.d.ts +2 -2
  295. package/dist/shared-tree-core/index.d.ts.map +1 -1
  296. package/dist/shared-tree-core/index.js +3 -1
  297. package/dist/shared-tree-core/index.js.map +1 -1
  298. package/dist/shared-tree-core/messageCodecV1ToV4.d.ts +1 -1
  299. package/dist/shared-tree-core/messageCodecV1ToV4.d.ts.map +1 -1
  300. package/dist/shared-tree-core/messageCodecV1ToV4.js.map +1 -1
  301. package/dist/shared-tree-core/messageCodecs.d.ts +4 -0
  302. package/dist/shared-tree-core/messageCodecs.d.ts.map +1 -1
  303. package/dist/shared-tree-core/messageCodecs.js +10 -2
  304. package/dist/shared-tree-core/messageCodecs.js.map +1 -1
  305. package/dist/shared-tree-core/messageFormat.d.ts +1 -0
  306. package/dist/shared-tree-core/messageFormat.d.ts.map +1 -1
  307. package/dist/shared-tree-core/messageFormat.js +6 -0
  308. package/dist/shared-tree-core/messageFormat.js.map +1 -1
  309. package/dist/shared-tree-core/messageFormatV1ToV4.d.ts +2 -2
  310. package/dist/shared-tree-core/messageFormatV1ToV4.d.ts.map +1 -1
  311. package/dist/shared-tree-core/messageFormatV1ToV4.js +1 -0
  312. package/dist/shared-tree-core/messageFormatV1ToV4.js.map +1 -1
  313. package/dist/shared-tree-core/sharedTreeCore.d.ts +1 -0
  314. package/dist/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
  315. package/dist/shared-tree-core/sharedTreeCore.js +1 -1
  316. package/dist/shared-tree-core/sharedTreeCore.js.map +1 -1
  317. package/dist/simple-tree/api/index.d.ts +1 -1
  318. package/dist/simple-tree/api/index.d.ts.map +1 -1
  319. package/dist/simple-tree/api/index.js +2 -1
  320. package/dist/simple-tree/api/index.js.map +1 -1
  321. package/dist/simple-tree/api/schemaFactoryAlpha.js +1 -1
  322. package/dist/simple-tree/api/schemaFactoryAlpha.js.map +1 -1
  323. package/dist/simple-tree/api/schemaFactoryBeta.js +1 -1
  324. package/dist/simple-tree/api/schemaFactoryBeta.js.map +1 -1
  325. package/dist/simple-tree/api/simpleSchemaToJsonSchema.js +4 -4
  326. package/dist/simple-tree/api/simpleSchemaToJsonSchema.js.map +1 -1
  327. package/dist/simple-tree/api/snapshotCompatibilityChecker.d.ts +244 -0
  328. package/dist/simple-tree/api/snapshotCompatibilityChecker.d.ts.map +1 -1
  329. package/dist/simple-tree/api/snapshotCompatibilityChecker.js +297 -1
  330. package/dist/simple-tree/api/snapshotCompatibilityChecker.js.map +1 -1
  331. package/dist/simple-tree/api/tree.d.ts +3 -1
  332. package/dist/simple-tree/api/tree.d.ts.map +1 -1
  333. package/dist/simple-tree/api/tree.js.map +1 -1
  334. package/dist/simple-tree/core/treeNodeKernel.d.ts.map +1 -1
  335. package/dist/simple-tree/core/treeNodeKernel.js +6 -2
  336. package/dist/simple-tree/core/treeNodeKernel.js.map +1 -1
  337. package/dist/simple-tree/core/unhydratedFlexTree.d.ts +15 -15
  338. package/dist/simple-tree/core/unhydratedFlexTree.d.ts.map +1 -1
  339. package/dist/simple-tree/core/unhydratedFlexTree.js +59 -8
  340. package/dist/simple-tree/core/unhydratedFlexTree.js.map +1 -1
  341. package/dist/simple-tree/fieldSchema.d.ts +4 -4
  342. package/dist/simple-tree/fieldSchema.d.ts.map +1 -1
  343. package/dist/simple-tree/fieldSchema.js.map +1 -1
  344. package/dist/simple-tree/index.d.ts +3 -3
  345. package/dist/simple-tree/index.d.ts.map +1 -1
  346. package/dist/simple-tree/index.js +4 -3
  347. package/dist/simple-tree/index.js.map +1 -1
  348. package/dist/simple-tree/node-kinds/array/arrayNode.d.ts.map +1 -1
  349. package/dist/simple-tree/node-kinds/array/arrayNode.js +7 -5
  350. package/dist/simple-tree/node-kinds/array/arrayNode.js.map +1 -1
  351. package/dist/simple-tree/node-kinds/common.d.ts.map +1 -1
  352. package/dist/simple-tree/node-kinds/common.js +1 -1
  353. package/dist/simple-tree/node-kinds/common.js.map +1 -1
  354. package/dist/simple-tree/node-kinds/map/mapNode.js +2 -2
  355. package/dist/simple-tree/node-kinds/map/mapNode.js.map +1 -1
  356. package/dist/simple-tree/node-kinds/object/objectNode.d.ts.map +1 -1
  357. package/dist/simple-tree/node-kinds/object/objectNode.js +19 -19
  358. package/dist/simple-tree/node-kinds/object/objectNode.js.map +1 -1
  359. package/dist/simple-tree/node-kinds/record/recordNode.d.ts.map +1 -1
  360. package/dist/simple-tree/node-kinds/record/recordNode.js +4 -2
  361. package/dist/simple-tree/node-kinds/record/recordNode.js.map +1 -1
  362. package/dist/simple-tree/prepareForInsertion.d.ts +54 -47
  363. package/dist/simple-tree/prepareForInsertion.d.ts.map +1 -1
  364. package/dist/simple-tree/prepareForInsertion.js +184 -126
  365. package/dist/simple-tree/prepareForInsertion.js.map +1 -1
  366. package/dist/simple-tree/unhydratedFlexTreeFromInsertable.d.ts +13 -4
  367. package/dist/simple-tree/unhydratedFlexTreeFromInsertable.d.ts.map +1 -1
  368. package/dist/simple-tree/unhydratedFlexTreeFromInsertable.js +31 -13
  369. package/dist/simple-tree/unhydratedFlexTreeFromInsertable.js.map +1 -1
  370. package/dist/text/index.d.ts +6 -0
  371. package/dist/text/index.d.ts.map +1 -0
  372. package/dist/text/index.js +10 -0
  373. package/dist/text/index.js.map +1 -0
  374. package/dist/text/textDomain.d.ts +138 -0
  375. package/dist/text/textDomain.d.ts.map +1 -0
  376. package/dist/text/textDomain.js +121 -0
  377. package/dist/text/textDomain.js.map +1 -0
  378. package/dist/treeFactory.d.ts.map +1 -1
  379. package/dist/treeFactory.js +12 -2
  380. package/dist/treeFactory.js.map +1 -1
  381. package/dist/util/bTreeUtils.d.ts +12 -4
  382. package/dist/util/bTreeUtils.d.ts.map +1 -1
  383. package/dist/util/bTreeUtils.js +14 -18
  384. package/dist/util/bTreeUtils.js.map +1 -1
  385. package/dist/util/index.d.ts +1 -1
  386. package/dist/util/index.d.ts.map +1 -1
  387. package/dist/util/index.js +2 -1
  388. package/dist/util/index.js.map +1 -1
  389. package/dist/util/nestedMap.js +12 -12
  390. package/dist/util/nestedMap.js.map +1 -1
  391. package/dist/util/rangeMap.d.ts +24 -12
  392. package/dist/util/rangeMap.d.ts.map +1 -1
  393. package/dist/util/rangeMap.js +46 -6
  394. package/dist/util/rangeMap.js.map +1 -1
  395. package/docs/user-facing/merge-semantics.md +3 -2
  396. package/eslint.config.mts +4 -32
  397. package/lib/alpha.d.ts +5 -0
  398. package/lib/core/change-family/changeFamily.d.ts +4 -1
  399. package/lib/core/change-family/changeFamily.d.ts.map +1 -1
  400. package/lib/core/change-family/changeFamily.js.map +1 -1
  401. package/lib/core/change-family/index.d.ts +1 -1
  402. package/lib/core/change-family/index.d.ts.map +1 -1
  403. package/lib/core/change-family/index.js.map +1 -1
  404. package/lib/core/index.d.ts +3 -3
  405. package/lib/core/index.d.ts.map +1 -1
  406. package/lib/core/index.js +2 -2
  407. package/lib/core/index.js.map +1 -1
  408. package/lib/core/rebase/changeRebaser.d.ts +6 -1
  409. package/lib/core/rebase/changeRebaser.d.ts.map +1 -1
  410. package/lib/core/rebase/changeRebaser.js.map +1 -1
  411. package/lib/core/rebase/index.d.ts +1 -1
  412. package/lib/core/rebase/index.d.ts.map +1 -1
  413. package/lib/core/rebase/index.js +1 -1
  414. package/lib/core/rebase/index.js.map +1 -1
  415. package/lib/core/rebase/types.d.ts +46 -8
  416. package/lib/core/rebase/types.d.ts.map +1 -1
  417. package/lib/core/rebase/types.js +3 -0
  418. package/lib/core/rebase/types.js.map +1 -1
  419. package/lib/core/rebase/utils.d.ts.map +1 -1
  420. package/lib/core/rebase/utils.js +30 -8
  421. package/lib/core/rebase/utils.js.map +1 -1
  422. package/lib/core/tree/anchorSet.js +1 -0
  423. package/lib/core/tree/anchorSet.js.map +1 -1
  424. package/lib/core/tree/detachedFieldIndex.d.ts +6 -0
  425. package/lib/core/tree/detachedFieldIndex.d.ts.map +1 -1
  426. package/lib/core/tree/detachedFieldIndex.js +10 -1
  427. package/lib/core/tree/detachedFieldIndex.js.map +1 -1
  428. package/lib/core/tree/index.d.ts +1 -1
  429. package/lib/core/tree/index.d.ts.map +1 -1
  430. package/lib/core/tree/index.js +1 -1
  431. package/lib/core/tree/index.js.map +1 -1
  432. package/lib/core/tree/pathTree.d.ts +11 -3
  433. package/lib/core/tree/pathTree.d.ts.map +1 -1
  434. package/lib/core/tree/pathTree.js +12 -1
  435. package/lib/core/tree/pathTree.js.map +1 -1
  436. package/lib/core/tree/visitDelta.d.ts.map +1 -1
  437. package/lib/core/tree/visitDelta.js +3 -2
  438. package/lib/core/tree/visitDelta.js.map +1 -1
  439. package/lib/core/tree/visitorUtils.d.ts.map +1 -1
  440. package/lib/core/tree/visitorUtils.js +58 -18
  441. package/lib/core/tree/visitorUtils.js.map +1 -1
  442. package/lib/feature-libraries/changeAtomIdBTree.d.ts +10 -4
  443. package/lib/feature-libraries/changeAtomIdBTree.d.ts.map +1 -1
  444. package/lib/feature-libraries/changeAtomIdBTree.js +14 -1
  445. package/lib/feature-libraries/changeAtomIdBTree.js.map +1 -1
  446. package/lib/feature-libraries/chunked-forest/basicChunk.d.ts.map +1 -1
  447. package/lib/feature-libraries/chunked-forest/basicChunk.js +8 -1
  448. package/lib/feature-libraries/chunked-forest/basicChunk.js.map +1 -1
  449. package/lib/feature-libraries/chunked-forest/chunkTree.d.ts.map +1 -1
  450. package/lib/feature-libraries/chunked-forest/chunkTree.js +4 -1
  451. package/lib/feature-libraries/chunked-forest/chunkTree.js.map +1 -1
  452. package/lib/feature-libraries/chunked-forest/chunkedForest.d.ts.map +1 -1
  453. package/lib/feature-libraries/chunked-forest/chunkedForest.js +3 -1
  454. package/lib/feature-libraries/chunked-forest/chunkedForest.js.map +1 -1
  455. package/lib/feature-libraries/chunked-forest/codec/compressedEncode.js +1 -0
  456. package/lib/feature-libraries/chunked-forest/codec/compressedEncode.js.map +1 -1
  457. package/lib/feature-libraries/default-schema/defaultEditBuilder.d.ts +93 -44
  458. package/lib/feature-libraries/default-schema/defaultEditBuilder.d.ts.map +1 -1
  459. package/lib/feature-libraries/default-schema/defaultEditBuilder.js +236 -70
  460. package/lib/feature-libraries/default-schema/defaultEditBuilder.js.map +1 -1
  461. package/lib/feature-libraries/default-schema/defaultFieldKinds.d.ts +1 -1
  462. package/lib/feature-libraries/default-schema/defaultFieldKinds.d.ts.map +1 -1
  463. package/lib/feature-libraries/default-schema/defaultFieldKinds.js +11 -2
  464. package/lib/feature-libraries/default-schema/defaultFieldKinds.js.map +1 -1
  465. package/lib/feature-libraries/default-schema/index.d.ts +2 -1
  466. package/lib/feature-libraries/default-schema/index.d.ts.map +1 -1
  467. package/lib/feature-libraries/default-schema/index.js +2 -1
  468. package/lib/feature-libraries/default-schema/index.js.map +1 -1
  469. package/lib/feature-libraries/default-schema/locationBasedEditBuilder.d.ts +38 -0
  470. package/lib/feature-libraries/default-schema/locationBasedEditBuilder.d.ts.map +1 -0
  471. package/lib/feature-libraries/default-schema/locationBasedEditBuilder.js +128 -0
  472. package/lib/feature-libraries/default-schema/locationBasedEditBuilder.js.map +1 -0
  473. package/lib/feature-libraries/default-schema/mappedEditBuilder.d.ts +7 -6
  474. package/lib/feature-libraries/default-schema/mappedEditBuilder.d.ts.map +1 -1
  475. package/lib/feature-libraries/default-schema/mappedEditBuilder.js +15 -0
  476. package/lib/feature-libraries/default-schema/mappedEditBuilder.js.map +1 -1
  477. package/lib/feature-libraries/deltaUtils.d.ts +1 -0
  478. package/lib/feature-libraries/deltaUtils.d.ts.map +1 -1
  479. package/lib/feature-libraries/deltaUtils.js +5 -1
  480. package/lib/feature-libraries/deltaUtils.js.map +1 -1
  481. package/lib/feature-libraries/flex-tree/context.d.ts +9 -0
  482. package/lib/feature-libraries/flex-tree/context.d.ts.map +1 -1
  483. package/lib/feature-libraries/flex-tree/context.js +6 -0
  484. package/lib/feature-libraries/flex-tree/context.js.map +1 -1
  485. package/lib/feature-libraries/flex-tree/flexTreeTypes.d.ts +6 -6
  486. package/lib/feature-libraries/flex-tree/flexTreeTypes.d.ts.map +1 -1
  487. package/lib/feature-libraries/flex-tree/flexTreeTypes.js.map +1 -1
  488. package/lib/feature-libraries/flex-tree/lazyField.d.ts +8 -7
  489. package/lib/feature-libraries/flex-tree/lazyField.d.ts.map +1 -1
  490. package/lib/feature-libraries/flex-tree/lazyField.js +41 -10
  491. package/lib/feature-libraries/flex-tree/lazyField.js.map +1 -1
  492. package/lib/feature-libraries/forest-summary/forestSummarizer.d.ts.map +1 -1
  493. package/lib/feature-libraries/forest-summary/forestSummarizer.js +3 -1
  494. package/lib/feature-libraries/forest-summary/forestSummarizer.js.map +1 -1
  495. package/lib/feature-libraries/index.d.ts +3 -3
  496. package/lib/feature-libraries/index.d.ts.map +1 -1
  497. package/lib/feature-libraries/index.js +2 -2
  498. package/lib/feature-libraries/index.js.map +1 -1
  499. package/lib/feature-libraries/mapTreeCursor.d.ts.map +1 -1
  500. package/lib/feature-libraries/mapTreeCursor.js +2 -1
  501. package/lib/feature-libraries/mapTreeCursor.js.map +1 -1
  502. package/lib/feature-libraries/mitigatedChangeFamily.d.ts.map +1 -1
  503. package/lib/feature-libraries/mitigatedChangeFamily.js +2 -2
  504. package/lib/feature-libraries/mitigatedChangeFamily.js.map +1 -1
  505. package/lib/feature-libraries/modular-schema/crossFieldQueries.d.ts +97 -21
  506. package/lib/feature-libraries/modular-schema/crossFieldQueries.d.ts.map +1 -1
  507. package/lib/feature-libraries/modular-schema/crossFieldQueries.js +3 -5
  508. package/lib/feature-libraries/modular-schema/crossFieldQueries.js.map +1 -1
  509. package/lib/feature-libraries/modular-schema/fieldChangeHandler.d.ts +20 -51
  510. package/lib/feature-libraries/modular-schema/fieldChangeHandler.d.ts.map +1 -1
  511. package/lib/feature-libraries/modular-schema/fieldChangeHandler.js.map +1 -1
  512. package/lib/feature-libraries/modular-schema/genericFieldKind.d.ts.map +1 -1
  513. package/lib/feature-libraries/modular-schema/genericFieldKind.js +3 -9
  514. package/lib/feature-libraries/modular-schema/genericFieldKind.js.map +1 -1
  515. package/lib/feature-libraries/modular-schema/index.d.ts +4 -4
  516. package/lib/feature-libraries/modular-schema/index.d.ts.map +1 -1
  517. package/lib/feature-libraries/modular-schema/index.js +2 -2
  518. package/lib/feature-libraries/modular-schema/index.js.map +1 -1
  519. package/lib/feature-libraries/modular-schema/modularChangeCodecV1.d.ts +11 -28
  520. package/lib/feature-libraries/modular-schema/modularChangeCodecV1.d.ts.map +1 -1
  521. package/lib/feature-libraries/modular-schema/modularChangeCodecV1.js +247 -143
  522. package/lib/feature-libraries/modular-schema/modularChangeCodecV1.js.map +1 -1
  523. package/lib/feature-libraries/modular-schema/modularChangeCodecV3.d.ts +15 -0
  524. package/lib/feature-libraries/modular-schema/modularChangeCodecV3.d.ts.map +1 -0
  525. package/lib/feature-libraries/modular-schema/modularChangeCodecV3.js +389 -0
  526. package/lib/feature-libraries/modular-schema/modularChangeCodecV3.js.map +1 -0
  527. package/lib/feature-libraries/modular-schema/modularChangeCodecs.d.ts.map +1 -1
  528. package/lib/feature-libraries/modular-schema/modularChangeCodecs.js +8 -1
  529. package/lib/feature-libraries/modular-schema/modularChangeCodecs.js.map +1 -1
  530. package/lib/feature-libraries/modular-schema/modularChangeFamily.d.ts +48 -20
  531. package/lib/feature-libraries/modular-schema/modularChangeFamily.d.ts.map +1 -1
  532. package/lib/feature-libraries/modular-schema/modularChangeFamily.js +1344 -479
  533. package/lib/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
  534. package/lib/feature-libraries/modular-schema/modularChangeFormatV1.d.ts.map +1 -1
  535. package/lib/feature-libraries/modular-schema/modularChangeFormatV1.js.map +1 -1
  536. package/lib/feature-libraries/modular-schema/modularChangeFormatV3.d.ts +146 -0
  537. package/lib/feature-libraries/modular-schema/modularChangeFormatV3.d.ts.map +1 -0
  538. package/lib/feature-libraries/modular-schema/modularChangeFormatV3.js +29 -0
  539. package/lib/feature-libraries/modular-schema/modularChangeFormatV3.js.map +1 -0
  540. package/lib/feature-libraries/modular-schema/modularChangeTypes.d.ts +47 -11
  541. package/lib/feature-libraries/modular-schema/modularChangeTypes.d.ts.map +1 -1
  542. package/lib/feature-libraries/modular-schema/modularChangeTypes.js +1 -1
  543. package/lib/feature-libraries/modular-schema/modularChangeTypes.js.map +1 -1
  544. package/lib/feature-libraries/object-forest/objectForest.d.ts.map +1 -1
  545. package/lib/feature-libraries/object-forest/objectForest.js +3 -1
  546. package/lib/feature-libraries/object-forest/objectForest.js.map +1 -1
  547. package/lib/feature-libraries/optional-field/index.d.ts +2 -2
  548. package/lib/feature-libraries/optional-field/index.d.ts.map +1 -1
  549. package/lib/feature-libraries/optional-field/index.js +1 -1
  550. package/lib/feature-libraries/optional-field/index.js.map +1 -1
  551. package/lib/feature-libraries/optional-field/optionalField.d.ts +5 -26
  552. package/lib/feature-libraries/optional-field/optionalField.d.ts.map +1 -1
  553. package/lib/feature-libraries/optional-field/optionalField.js +221 -441
  554. package/lib/feature-libraries/optional-field/optionalField.js.map +1 -1
  555. package/lib/feature-libraries/optional-field/optionalFieldChangeFormatV3.d.ts +23 -0
  556. package/lib/feature-libraries/optional-field/optionalFieldChangeFormatV3.d.ts.map +1 -0
  557. package/lib/feature-libraries/optional-field/optionalFieldChangeFormatV3.js +27 -0
  558. package/lib/feature-libraries/optional-field/optionalFieldChangeFormatV3.js.map +1 -0
  559. package/lib/feature-libraries/optional-field/optionalFieldChangeTypes.d.ts +24 -33
  560. package/lib/feature-libraries/optional-field/optionalFieldChangeTypes.d.ts.map +1 -1
  561. package/lib/feature-libraries/optional-field/optionalFieldChangeTypes.js.map +1 -1
  562. package/lib/feature-libraries/optional-field/optionalFieldCodecV2.d.ts +1 -1
  563. package/lib/feature-libraries/optional-field/optionalFieldCodecV2.d.ts.map +1 -1
  564. package/lib/feature-libraries/optional-field/optionalFieldCodecV2.js +55 -26
  565. package/lib/feature-libraries/optional-field/optionalFieldCodecV2.js.map +1 -1
  566. package/lib/feature-libraries/optional-field/optionalFieldCodecV3.d.ts +12 -0
  567. package/lib/feature-libraries/optional-field/optionalFieldCodecV3.d.ts.map +1 -0
  568. package/lib/feature-libraries/optional-field/optionalFieldCodecV3.js +53 -0
  569. package/lib/feature-libraries/optional-field/optionalFieldCodecV3.js.map +1 -0
  570. package/lib/feature-libraries/optional-field/optionalFieldCodecs.d.ts.map +1 -1
  571. package/lib/feature-libraries/optional-field/optionalFieldCodecs.js +5 -1
  572. package/lib/feature-libraries/optional-field/optionalFieldCodecs.js.map +1 -1
  573. package/lib/feature-libraries/sequence-field/compose.d.ts +6 -7
  574. package/lib/feature-libraries/sequence-field/compose.d.ts.map +1 -1
  575. package/lib/feature-libraries/sequence-field/compose.js +85 -261
  576. package/lib/feature-libraries/sequence-field/compose.js.map +1 -1
  577. package/lib/feature-libraries/sequence-field/helperTypes.d.ts +14 -10
  578. package/lib/feature-libraries/sequence-field/helperTypes.d.ts.map +1 -1
  579. package/lib/feature-libraries/sequence-field/helperTypes.js.map +1 -1
  580. package/lib/feature-libraries/sequence-field/index.d.ts +2 -3
  581. package/lib/feature-libraries/sequence-field/index.d.ts.map +1 -1
  582. package/lib/feature-libraries/sequence-field/index.js +0 -1
  583. package/lib/feature-libraries/sequence-field/index.js.map +1 -1
  584. package/lib/feature-libraries/sequence-field/invert.d.ts +3 -3
  585. package/lib/feature-libraries/sequence-field/invert.d.ts.map +1 -1
  586. package/lib/feature-libraries/sequence-field/invert.js +67 -169
  587. package/lib/feature-libraries/sequence-field/invert.js.map +1 -1
  588. package/lib/feature-libraries/sequence-field/markQueue.d.ts +2 -2
  589. package/lib/feature-libraries/sequence-field/markQueue.d.ts.map +1 -1
  590. package/lib/feature-libraries/sequence-field/markQueue.js.map +1 -1
  591. package/lib/feature-libraries/sequence-field/moveEffectTable.d.ts +4 -56
  592. package/lib/feature-libraries/sequence-field/moveEffectTable.d.ts.map +1 -1
  593. package/lib/feature-libraries/sequence-field/moveEffectTable.js +6 -84
  594. package/lib/feature-libraries/sequence-field/moveEffectTable.js.map +1 -1
  595. package/lib/feature-libraries/sequence-field/rebase.d.ts +3 -3
  596. package/lib/feature-libraries/sequence-field/rebase.d.ts.map +1 -1
  597. package/lib/feature-libraries/sequence-field/rebase.js +109 -116
  598. package/lib/feature-libraries/sequence-field/rebase.js.map +1 -1
  599. package/lib/feature-libraries/sequence-field/replaceRevisions.d.ts.map +1 -1
  600. package/lib/feature-libraries/sequence-field/replaceRevisions.js +18 -31
  601. package/lib/feature-libraries/sequence-field/replaceRevisions.js.map +1 -1
  602. package/lib/feature-libraries/sequence-field/sequenceFieldChangeHandler.d.ts.map +1 -1
  603. package/lib/feature-libraries/sequence-field/sequenceFieldChangeHandler.js +0 -2
  604. package/lib/feature-libraries/sequence-field/sequenceFieldChangeHandler.js.map +1 -1
  605. package/lib/feature-libraries/sequence-field/sequenceFieldCodecV2.d.ts +22 -4
  606. package/lib/feature-libraries/sequence-field/sequenceFieldCodecV2.d.ts.map +1 -1
  607. package/lib/feature-libraries/sequence-field/sequenceFieldCodecV2.js +356 -182
  608. package/lib/feature-libraries/sequence-field/sequenceFieldCodecV2.js.map +1 -1
  609. package/lib/feature-libraries/sequence-field/sequenceFieldCodecV3.d.ts.map +1 -1
  610. package/lib/feature-libraries/sequence-field/sequenceFieldCodecV3.js +21 -63
  611. package/lib/feature-libraries/sequence-field/sequenceFieldCodecV3.js.map +1 -1
  612. package/lib/feature-libraries/sequence-field/sequenceFieldEditor.d.ts +2 -2
  613. package/lib/feature-libraries/sequence-field/sequenceFieldEditor.d.ts.map +1 -1
  614. package/lib/feature-libraries/sequence-field/sequenceFieldEditor.js +10 -10
  615. package/lib/feature-libraries/sequence-field/sequenceFieldEditor.js.map +1 -1
  616. package/lib/feature-libraries/sequence-field/sequenceFieldToDelta.d.ts +3 -2
  617. package/lib/feature-libraries/sequence-field/sequenceFieldToDelta.d.ts.map +1 -1
  618. package/lib/feature-libraries/sequence-field/sequenceFieldToDelta.js +14 -109
  619. package/lib/feature-libraries/sequence-field/sequenceFieldToDelta.js.map +1 -1
  620. package/lib/feature-libraries/sequence-field/types.d.ts +30 -59
  621. package/lib/feature-libraries/sequence-field/types.d.ts.map +1 -1
  622. package/lib/feature-libraries/sequence-field/types.js.map +1 -1
  623. package/lib/feature-libraries/sequence-field/utils.d.ts +15 -24
  624. package/lib/feature-libraries/sequence-field/utils.d.ts.map +1 -1
  625. package/lib/feature-libraries/sequence-field/utils.js +112 -298
  626. package/lib/feature-libraries/sequence-field/utils.js.map +1 -1
  627. package/lib/index.d.ts +3 -2
  628. package/lib/index.d.ts.map +1 -1
  629. package/lib/index.js +2 -1
  630. package/lib/index.js.map +1 -1
  631. package/lib/packageVersion.d.ts +1 -1
  632. package/lib/packageVersion.d.ts.map +1 -1
  633. package/lib/packageVersion.js +1 -1
  634. package/lib/packageVersion.js.map +1 -1
  635. package/lib/shared-tree/index.d.ts +1 -1
  636. package/lib/shared-tree/index.d.ts.map +1 -1
  637. package/lib/shared-tree/index.js.map +1 -1
  638. package/lib/shared-tree/schematizeTree.d.ts +4 -4
  639. package/lib/shared-tree/schematizeTree.d.ts.map +1 -1
  640. package/lib/shared-tree/schematizeTree.js +3 -2
  641. package/lib/shared-tree/schematizeTree.js.map +1 -1
  642. package/lib/shared-tree/schematizingTreeView.d.ts +1 -5
  643. package/lib/shared-tree/schematizingTreeView.d.ts.map +1 -1
  644. package/lib/shared-tree/schematizingTreeView.js +41 -38
  645. package/lib/shared-tree/schematizingTreeView.js.map +1 -1
  646. package/lib/shared-tree/sharedTree.d.ts +9 -3
  647. package/lib/shared-tree/sharedTree.d.ts.map +1 -1
  648. package/lib/shared-tree/sharedTree.js +11 -0
  649. package/lib/shared-tree/sharedTree.js.map +1 -1
  650. package/lib/shared-tree/sharedTreeChangeCodecs.d.ts +1 -1
  651. package/lib/shared-tree/sharedTreeChangeCodecs.d.ts.map +1 -1
  652. package/lib/shared-tree/sharedTreeChangeCodecs.js +1 -0
  653. package/lib/shared-tree/sharedTreeChangeCodecs.js.map +1 -1
  654. package/lib/shared-tree/sharedTreeChangeEnricher.d.ts.map +1 -1
  655. package/lib/shared-tree/sharedTreeChangeEnricher.js +2 -2
  656. package/lib/shared-tree/sharedTreeChangeEnricher.js.map +1 -1
  657. package/lib/shared-tree/sharedTreeChangeFamily.d.ts +5 -5
  658. package/lib/shared-tree/sharedTreeChangeFamily.d.ts.map +1 -1
  659. package/lib/shared-tree/sharedTreeChangeFamily.js +11 -5
  660. package/lib/shared-tree/sharedTreeChangeFamily.js.map +1 -1
  661. package/lib/shared-tree/sharedTreeEditBuilder.d.ts +16 -6
  662. package/lib/shared-tree/sharedTreeEditBuilder.d.ts.map +1 -1
  663. package/lib/shared-tree/sharedTreeEditBuilder.js +12 -6
  664. package/lib/shared-tree/sharedTreeEditBuilder.js.map +1 -1
  665. package/lib/shared-tree/treeCheckout.d.ts +9 -10
  666. package/lib/shared-tree/treeCheckout.d.ts.map +1 -1
  667. package/lib/shared-tree/treeCheckout.js +66 -11
  668. package/lib/shared-tree/treeCheckout.js.map +1 -1
  669. package/lib/shared-tree-core/branch.d.ts +3 -2
  670. package/lib/shared-tree-core/branch.d.ts.map +1 -1
  671. package/lib/shared-tree-core/branch.js +9 -4
  672. package/lib/shared-tree-core/branch.js.map +1 -1
  673. package/lib/shared-tree-core/editManager.d.ts +2 -2
  674. package/lib/shared-tree-core/editManager.d.ts.map +1 -1
  675. package/lib/shared-tree-core/editManager.js +20 -14
  676. package/lib/shared-tree-core/editManager.js.map +1 -1
  677. package/lib/shared-tree-core/editManagerCodecs.d.ts +4 -0
  678. package/lib/shared-tree-core/editManagerCodecs.d.ts.map +1 -1
  679. package/lib/shared-tree-core/editManagerCodecs.js +8 -1
  680. package/lib/shared-tree-core/editManagerCodecs.js.map +1 -1
  681. package/lib/shared-tree-core/editManagerFormatCommons.d.ts +1 -0
  682. package/lib/shared-tree-core/editManagerFormatCommons.d.ts.map +1 -1
  683. package/lib/shared-tree-core/editManagerFormatCommons.js +6 -0
  684. package/lib/shared-tree-core/editManagerFormatCommons.js.map +1 -1
  685. package/lib/shared-tree-core/editManagerFormatV1toV4.d.ts +2 -2
  686. package/lib/shared-tree-core/editManagerFormatV1toV4.d.ts.map +1 -1
  687. package/lib/shared-tree-core/editManagerFormatV1toV4.js +1 -0
  688. package/lib/shared-tree-core/editManagerFormatV1toV4.js.map +1 -1
  689. package/lib/shared-tree-core/index.d.ts +2 -2
  690. package/lib/shared-tree-core/index.d.ts.map +1 -1
  691. package/lib/shared-tree-core/index.js +2 -2
  692. package/lib/shared-tree-core/index.js.map +1 -1
  693. package/lib/shared-tree-core/messageCodecV1ToV4.d.ts +1 -1
  694. package/lib/shared-tree-core/messageCodecV1ToV4.d.ts.map +1 -1
  695. package/lib/shared-tree-core/messageCodecV1ToV4.js.map +1 -1
  696. package/lib/shared-tree-core/messageCodecs.d.ts +4 -0
  697. package/lib/shared-tree-core/messageCodecs.d.ts.map +1 -1
  698. package/lib/shared-tree-core/messageCodecs.js +8 -1
  699. package/lib/shared-tree-core/messageCodecs.js.map +1 -1
  700. package/lib/shared-tree-core/messageFormat.d.ts +1 -0
  701. package/lib/shared-tree-core/messageFormat.d.ts.map +1 -1
  702. package/lib/shared-tree-core/messageFormat.js +6 -0
  703. package/lib/shared-tree-core/messageFormat.js.map +1 -1
  704. package/lib/shared-tree-core/messageFormatV1ToV4.d.ts +2 -2
  705. package/lib/shared-tree-core/messageFormatV1ToV4.d.ts.map +1 -1
  706. package/lib/shared-tree-core/messageFormatV1ToV4.js +1 -0
  707. package/lib/shared-tree-core/messageFormatV1ToV4.js.map +1 -1
  708. package/lib/shared-tree-core/sharedTreeCore.d.ts +1 -0
  709. package/lib/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
  710. package/lib/shared-tree-core/sharedTreeCore.js +1 -1
  711. package/lib/shared-tree-core/sharedTreeCore.js.map +1 -1
  712. package/lib/simple-tree/api/index.d.ts +1 -1
  713. package/lib/simple-tree/api/index.d.ts.map +1 -1
  714. package/lib/simple-tree/api/index.js +1 -1
  715. package/lib/simple-tree/api/index.js.map +1 -1
  716. package/lib/simple-tree/api/schemaFactoryAlpha.js +1 -1
  717. package/lib/simple-tree/api/schemaFactoryAlpha.js.map +1 -1
  718. package/lib/simple-tree/api/schemaFactoryBeta.js +1 -1
  719. package/lib/simple-tree/api/schemaFactoryBeta.js.map +1 -1
  720. package/lib/simple-tree/api/simpleSchemaToJsonSchema.js +4 -4
  721. package/lib/simple-tree/api/simpleSchemaToJsonSchema.js.map +1 -1
  722. package/lib/simple-tree/api/snapshotCompatibilityChecker.d.ts +244 -0
  723. package/lib/simple-tree/api/snapshotCompatibilityChecker.d.ts.map +1 -1
  724. package/lib/simple-tree/api/snapshotCompatibilityChecker.js +270 -0
  725. package/lib/simple-tree/api/snapshotCompatibilityChecker.js.map +1 -1
  726. package/lib/simple-tree/api/tree.d.ts +3 -1
  727. package/lib/simple-tree/api/tree.d.ts.map +1 -1
  728. package/lib/simple-tree/api/tree.js.map +1 -1
  729. package/lib/simple-tree/core/treeNodeKernel.d.ts.map +1 -1
  730. package/lib/simple-tree/core/treeNodeKernel.js +6 -2
  731. package/lib/simple-tree/core/treeNodeKernel.js.map +1 -1
  732. package/lib/simple-tree/core/unhydratedFlexTree.d.ts +15 -15
  733. package/lib/simple-tree/core/unhydratedFlexTree.d.ts.map +1 -1
  734. package/lib/simple-tree/core/unhydratedFlexTree.js +58 -8
  735. package/lib/simple-tree/core/unhydratedFlexTree.js.map +1 -1
  736. package/lib/simple-tree/fieldSchema.d.ts +4 -4
  737. package/lib/simple-tree/fieldSchema.d.ts.map +1 -1
  738. package/lib/simple-tree/fieldSchema.js.map +1 -1
  739. package/lib/simple-tree/index.d.ts +3 -3
  740. package/lib/simple-tree/index.d.ts.map +1 -1
  741. package/lib/simple-tree/index.js +2 -2
  742. package/lib/simple-tree/index.js.map +1 -1
  743. package/lib/simple-tree/node-kinds/array/arrayNode.d.ts.map +1 -1
  744. package/lib/simple-tree/node-kinds/array/arrayNode.js +8 -6
  745. package/lib/simple-tree/node-kinds/array/arrayNode.js.map +1 -1
  746. package/lib/simple-tree/node-kinds/common.d.ts.map +1 -1
  747. package/lib/simple-tree/node-kinds/common.js +2 -2
  748. package/lib/simple-tree/node-kinds/common.js.map +1 -1
  749. package/lib/simple-tree/node-kinds/map/mapNode.js +2 -2
  750. package/lib/simple-tree/node-kinds/map/mapNode.js.map +1 -1
  751. package/lib/simple-tree/node-kinds/object/objectNode.d.ts.map +1 -1
  752. package/lib/simple-tree/node-kinds/object/objectNode.js +20 -20
  753. package/lib/simple-tree/node-kinds/object/objectNode.js.map +1 -1
  754. package/lib/simple-tree/node-kinds/record/recordNode.d.ts.map +1 -1
  755. package/lib/simple-tree/node-kinds/record/recordNode.js +4 -2
  756. package/lib/simple-tree/node-kinds/record/recordNode.js.map +1 -1
  757. package/lib/simple-tree/prepareForInsertion.d.ts +54 -47
  758. package/lib/simple-tree/prepareForInsertion.d.ts.map +1 -1
  759. package/lib/simple-tree/prepareForInsertion.js +184 -125
  760. package/lib/simple-tree/prepareForInsertion.js.map +1 -1
  761. package/lib/simple-tree/unhydratedFlexTreeFromInsertable.d.ts +13 -4
  762. package/lib/simple-tree/unhydratedFlexTreeFromInsertable.d.ts.map +1 -1
  763. package/lib/simple-tree/unhydratedFlexTreeFromInsertable.js +28 -11
  764. package/lib/simple-tree/unhydratedFlexTreeFromInsertable.js.map +1 -1
  765. package/lib/text/index.d.ts +6 -0
  766. package/lib/text/index.d.ts.map +1 -0
  767. package/lib/text/index.js +6 -0
  768. package/lib/text/index.js.map +1 -0
  769. package/lib/text/textDomain.d.ts +138 -0
  770. package/lib/text/textDomain.d.ts.map +1 -0
  771. package/lib/text/textDomain.js +118 -0
  772. package/lib/text/textDomain.js.map +1 -0
  773. package/lib/treeFactory.d.ts.map +1 -1
  774. package/lib/treeFactory.js +13 -3
  775. package/lib/treeFactory.js.map +1 -1
  776. package/lib/util/bTreeUtils.d.ts +12 -4
  777. package/lib/util/bTreeUtils.d.ts.map +1 -1
  778. package/lib/util/bTreeUtils.js +15 -19
  779. package/lib/util/bTreeUtils.js.map +1 -1
  780. package/lib/util/index.d.ts +1 -1
  781. package/lib/util/index.d.ts.map +1 -1
  782. package/lib/util/index.js +1 -1
  783. package/lib/util/index.js.map +1 -1
  784. package/lib/util/nestedMap.js +12 -12
  785. package/lib/util/nestedMap.js.map +1 -1
  786. package/lib/util/rangeMap.d.ts +24 -12
  787. package/lib/util/rangeMap.d.ts.map +1 -1
  788. package/lib/util/rangeMap.js +44 -5
  789. package/lib/util/rangeMap.js.map +1 -1
  790. package/package.json +25 -25
  791. package/src/core/change-family/changeFamily.ts +5 -0
  792. package/src/core/change-family/index.ts +1 -0
  793. package/src/core/index.ts +6 -1
  794. package/src/core/rebase/changeRebaser.ts +6 -1
  795. package/src/core/rebase/index.ts +3 -0
  796. package/src/core/rebase/types.ts +65 -21
  797. package/src/core/rebase/utils.ts +39 -11
  798. package/src/core/tree/anchorSet.ts +1 -0
  799. package/src/core/tree/detachedFieldIndex.ts +17 -1
  800. package/src/core/tree/index.ts +2 -1
  801. package/src/core/tree/pathTree.ts +16 -4
  802. package/src/core/tree/visitDelta.ts +6 -2
  803. package/src/core/tree/visitorUtils.ts +55 -19
  804. package/src/feature-libraries/changeAtomIdBTree.ts +37 -5
  805. package/src/feature-libraries/chunked-forest/basicChunk.ts +7 -1
  806. package/src/feature-libraries/chunked-forest/chunkTree.ts +6 -1
  807. package/src/feature-libraries/chunked-forest/chunkedForest.ts +3 -1
  808. package/src/feature-libraries/chunked-forest/codec/compressedEncode.ts +1 -0
  809. package/src/feature-libraries/default-schema/defaultEditBuilder.ts +399 -127
  810. package/src/feature-libraries/default-schema/defaultFieldKinds.ts +13 -5
  811. package/src/feature-libraries/default-schema/index.ts +17 -5
  812. package/src/feature-libraries/default-schema/locationBasedEditBuilder.ts +188 -0
  813. package/src/feature-libraries/default-schema/mappedEditBuilder.ts +35 -9
  814. package/src/feature-libraries/deltaUtils.ts +6 -1
  815. package/src/feature-libraries/flex-tree/context.ts +17 -0
  816. package/src/feature-libraries/flex-tree/flexTreeTypes.ts +7 -8
  817. package/src/feature-libraries/flex-tree/lazyField.ts +68 -25
  818. package/src/feature-libraries/forest-summary/forestSummarizer.ts +3 -1
  819. package/src/feature-libraries/index.ts +22 -8
  820. package/src/feature-libraries/mapTreeCursor.ts +2 -1
  821. package/src/feature-libraries/mitigatedChangeFamily.ts +3 -1
  822. package/src/feature-libraries/modular-schema/crossFieldQueries.ts +142 -44
  823. package/src/feature-libraries/modular-schema/fieldChangeHandler.ts +32 -58
  824. package/src/feature-libraries/modular-schema/genericFieldKind.ts +6 -18
  825. package/src/feature-libraries/modular-schema/index.ts +16 -15
  826. package/src/feature-libraries/modular-schema/modularChangeCodecV1.ts +560 -351
  827. package/src/feature-libraries/modular-schema/modularChangeCodecV3.ts +760 -0
  828. package/src/feature-libraries/modular-schema/modularChangeCodecs.ts +14 -1
  829. package/src/feature-libraries/modular-schema/modularChangeFamily.ts +2620 -782
  830. package/src/feature-libraries/modular-schema/modularChangeFormatV1.ts +1 -0
  831. package/src/feature-libraries/modular-schema/modularChangeFormatV3.ts +62 -0
  832. package/src/feature-libraries/modular-schema/modularChangeTypes.ts +58 -11
  833. package/src/feature-libraries/object-forest/objectForest.ts +3 -1
  834. package/src/feature-libraries/optional-field/index.ts +1 -3
  835. package/src/feature-libraries/optional-field/optionalField.ts +318 -562
  836. package/src/feature-libraries/optional-field/optionalFieldChangeFormatV3.ts +45 -0
  837. package/src/feature-libraries/optional-field/optionalFieldChangeTypes.ts +24 -38
  838. package/src/feature-libraries/optional-field/optionalFieldCodecV2.ts +89 -35
  839. package/src/feature-libraries/optional-field/optionalFieldCodecV3.ts +94 -0
  840. package/src/feature-libraries/optional-field/optionalFieldCodecs.ts +5 -1
  841. package/src/feature-libraries/sequence-field/compose.ts +139 -522
  842. package/src/feature-libraries/sequence-field/helperTypes.ts +34 -19
  843. package/src/feature-libraries/sequence-field/index.ts +0 -9
  844. package/src/feature-libraries/sequence-field/invert.ts +103 -228
  845. package/src/feature-libraries/sequence-field/markQueue.ts +2 -2
  846. package/src/feature-libraries/sequence-field/moveEffectTable.ts +8 -195
  847. package/src/feature-libraries/sequence-field/rebase.ts +169 -205
  848. package/src/feature-libraries/sequence-field/replaceRevisions.ts +25 -47
  849. package/src/feature-libraries/sequence-field/sequenceFieldChangeHandler.ts +0 -2
  850. package/src/feature-libraries/sequence-field/sequenceFieldCodecV2.ts +648 -228
  851. package/src/feature-libraries/sequence-field/sequenceFieldCodecV3.ts +56 -70
  852. package/src/feature-libraries/sequence-field/sequenceFieldEditor.ts +25 -27
  853. package/src/feature-libraries/sequence-field/sequenceFieldToDelta.ts +19 -129
  854. package/src/feature-libraries/sequence-field/types.ts +34 -64
  855. package/src/feature-libraries/sequence-field/utils.ts +139 -353
  856. package/src/index.ts +7 -0
  857. package/src/packageVersion.ts +1 -1
  858. package/src/shared-tree/index.ts +3 -2
  859. package/src/shared-tree/schematizeTree.ts +21 -8
  860. package/src/shared-tree/schematizingTreeView.ts +56 -70
  861. package/src/shared-tree/sharedTree.ts +20 -3
  862. package/src/shared-tree/sharedTreeChangeCodecs.ts +5 -1
  863. package/src/shared-tree/sharedTreeChangeEnricher.ts +2 -0
  864. package/src/shared-tree/sharedTreeChangeFamily.ts +15 -5
  865. package/src/shared-tree/sharedTreeEditBuilder.ts +39 -8
  866. package/src/shared-tree/treeCheckout.ts +95 -24
  867. package/src/shared-tree-core/branch.ts +13 -3
  868. package/src/shared-tree-core/editManager.ts +42 -28
  869. package/src/shared-tree-core/editManagerCodecs.ts +11 -1
  870. package/src/shared-tree-core/editManagerFormatCommons.ts +6 -0
  871. package/src/shared-tree-core/editManagerFormatV1toV4.ts +3 -1
  872. package/src/shared-tree-core/index.ts +2 -0
  873. package/src/shared-tree-core/messageCodecV1ToV4.ts +2 -1
  874. package/src/shared-tree-core/messageCodecs.ts +11 -1
  875. package/src/shared-tree-core/messageFormat.ts +6 -0
  876. package/src/shared-tree-core/messageFormatV1ToV4.ts +3 -1
  877. package/src/shared-tree-core/sharedTreeCore.ts +4 -1
  878. package/src/simple-tree/api/index.ts +3 -0
  879. package/src/simple-tree/api/schemaFactoryAlpha.ts +1 -1
  880. package/src/simple-tree/api/schemaFactoryBeta.ts +1 -1
  881. package/src/simple-tree/api/simpleSchemaToJsonSchema.ts +4 -4
  882. package/src/simple-tree/api/snapshotCompatibilityChecker.ts +501 -0
  883. package/src/simple-tree/api/tree.ts +3 -1
  884. package/src/simple-tree/core/treeNodeKernel.ts +6 -2
  885. package/src/simple-tree/core/unhydratedFlexTree.ts +87 -36
  886. package/src/simple-tree/fieldSchema.ts +6 -4
  887. package/src/simple-tree/index.ts +5 -1
  888. package/src/simple-tree/node-kinds/array/arrayNode.ts +9 -7
  889. package/src/simple-tree/node-kinds/common.ts +2 -5
  890. package/src/simple-tree/node-kinds/map/mapNode.ts +4 -4
  891. package/src/simple-tree/node-kinds/object/objectNode.ts +26 -26
  892. package/src/simple-tree/node-kinds/record/recordNode.ts +10 -9
  893. package/src/simple-tree/prepareForInsertion.ts +343 -201
  894. package/src/simple-tree/unhydratedFlexTreeFromInsertable.ts +43 -15
  895. package/src/text/README.md +8 -0
  896. package/src/text/index.ts +6 -0
  897. package/src/text/textDomain.ts +199 -0
  898. package/src/treeFactory.ts +14 -4
  899. package/src/util/bTreeUtils.ts +33 -22
  900. package/src/util/index.ts +3 -0
  901. package/src/util/nestedMap.ts +12 -12
  902. package/src/util/rangeMap.ts +72 -18
  903. package/.eslintrc.cjs +0 -125
  904. package/assertTagging.config.mjs +0 -14
  905. package/dist/feature-libraries/sequence-field/relevantRemovedRoots.d.ts +0 -9
  906. package/dist/feature-libraries/sequence-field/relevantRemovedRoots.d.ts.map +0 -1
  907. package/dist/feature-libraries/sequence-field/relevantRemovedRoots.js +0 -50
  908. package/dist/feature-libraries/sequence-field/relevantRemovedRoots.js.map +0 -1
  909. package/docs/main/sequence-field/move-composition.md +0 -46
  910. package/lib/feature-libraries/sequence-field/relevantRemovedRoots.d.ts +0 -9
  911. package/lib/feature-libraries/sequence-field/relevantRemovedRoots.d.ts.map +0 -1
  912. package/lib/feature-libraries/sequence-field/relevantRemovedRoots.js +0 -46
  913. package/lib/feature-libraries/sequence-field/relevantRemovedRoots.js.map +0 -1
  914. package/src/feature-libraries/sequence-field/relevantRemovedRoots.ts +0 -57
@@ -4,7 +4,7 @@
4
4
  * Licensed under the MIT License.
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.normalizeFieldId = exports.getParentFieldId = exports.ModularEditBuilder = exports.getChangeHandler = exports.getFieldKind = exports.rebaseRevisionMetadataFromInfo = exports.intoDelta = exports.updateRefreshers = exports.relevantRemovedRoots = exports.ModularChangeFamily = void 0;
7
+ exports.validateChangeset = exports.addNodeRename = exports.getFirstAttachField = exports.getFirstDetachField = exports.cloneRootTable = exports.newRootTable = exports.normalizeNodeId = exports.normalizeFieldId = exports.getNodeParent = exports.buildModularChangesetFromField = exports.ModularEditBuilder = exports.getChangeHandler = exports.getFieldKind = exports.rebaseRevisionMetadataFromInfo = exports.intoDelta = exports.updateRefreshers = exports.getBuildIds = exports.relevantRemovedRoots = exports.ModularChangeFamily = void 0;
8
8
  const internal_1 = require("@fluidframework/core-utils/internal");
9
9
  const sorted_btree_es6_1 = require("@tylerbu/sorted-btree-es6");
10
10
  const internal_2 = require("@fluidframework/telemetry-utils/internal");
@@ -15,8 +15,8 @@ const crossFieldQueries_js_1 = require("./crossFieldQueries.js");
15
15
  const fieldChangeHandler_js_1 = require("./fieldChangeHandler.js");
16
16
  const genericFieldKind_js_1 = require("./genericFieldKind.js");
17
17
  const modularChangeTypes_js_1 = require("./modularChangeTypes.js");
18
- const changeAtomIdBTree_js_1 = require("../changeAtomIdBTree.js");
19
18
  const semver_ts_1 = require("semver-ts");
19
+ const changeAtomIdBTree_js_1 = require("../changeAtomIdBTree.js");
20
20
  /**
21
21
  * Implementation of ChangeFamily which delegates work in a given field to the appropriate FieldKind
22
22
  * as determined by the schema.
@@ -72,21 +72,22 @@ class ModularChangeFamily {
72
72
  return convertedChange;
73
73
  }
74
74
  compose(changes) {
75
- const { revInfos, maxId } = getRevInfoFromTaggedChanges(changes);
75
+ const { maxId } = getRevInfoFromTaggedChanges(changes);
76
76
  const idState = { maxId };
77
77
  const pairwiseDelegate = (left, right) => {
78
- return this.composePair(left, right, revInfos, idState);
78
+ return this.composePair(left, right, idState);
79
79
  };
80
80
  const innerChanges = changes.map((change) => change.change);
81
81
  return (0, index_js_3.balancedReduce)(innerChanges, pairwiseDelegate, makeModularChangeset);
82
82
  }
83
- composePair(change1, change2, revInfos, idState) {
84
- const { fieldChanges, nodeChanges, nodeToParent, nodeAliases, crossFieldKeys } = this.composeAllFields(change1, change2, revInfos, idState);
83
+ composePair(change1, change2, idState) {
84
+ const revInfos = composeRevInfos(change1.revisions, change2.revisions);
85
+ const { fieldChanges, nodeChanges, nodeToParent, nodeAliases, crossFieldKeys, rootNodes } = this.composeAllFields(change1, change2, revInfos, idState);
85
86
  const { allBuilds, allDestroys, allRefreshers } = composeBuildsDestroysAndRefreshers(change1, change2);
86
87
  // The composed changeset has a "no change" constraint if either change has one
87
88
  const noChangeConstraint = change1.noChangeConstraint ?? change2.noChangeConstraint;
88
89
  const noChangeConstraintOnRevert = change1.noChangeConstraintOnRevert ?? change2.noChangeConstraintOnRevert;
89
- return makeModularChangeset({
90
+ const composed = makeModularChangeset({
90
91
  fieldChanges,
91
92
  nodeChanges,
92
93
  nodeToParent,
@@ -94,12 +95,16 @@ class ModularChangeFamily {
94
95
  crossFieldKeys,
95
96
  maxId: idState.maxId,
96
97
  revisions: revInfos,
97
- noChangeConstraint,
98
- noChangeConstraintOnRevert,
98
+ rootNodes,
99
99
  builds: allBuilds,
100
100
  destroys: allDestroys,
101
101
  refreshers: allRefreshers,
102
+ noChangeConstraint,
103
+ noChangeConstraintOnRevert,
102
104
  });
105
+ // XXX: This is an expensive assert which should be disabled before merging.
106
+ validateChangeset(composed, this.fieldKinds);
107
+ return composed;
103
108
  }
104
109
  composeAllFields(potentiallyConflictedChange1, potentiallyConflictedChange2, revInfos, idState) {
105
110
  // Our current cell ordering scheme in sequences depends on being able to rebase over a change with conflicts.
@@ -120,34 +125,50 @@ class ModularChangeFamily {
120
125
  const composedNodeChanges = (0, index_js_3.brand)((0, index_js_3.mergeTupleBTrees)(change1.nodeChanges, change2.nodeChanges));
121
126
  const composedNodeToParent = (0, index_js_3.brand)((0, index_js_3.mergeTupleBTrees)(change1.nodeToParent, change2.nodeToParent));
122
127
  const composedNodeAliases = (0, index_js_3.brand)((0, index_js_3.mergeTupleBTrees)(change1.nodeAliases, change2.nodeAliases));
123
- const crossFieldTable = newComposeTable(change1, change2, composedNodeToParent);
128
+ const pendingCompositions = {
129
+ nodeIdsToCompose: [],
130
+ affectedBaseFields: (0, index_js_3.newTupleBTree)(),
131
+ };
132
+ const movedCrossFieldKeys = (0, modularChangeTypes_js_1.newCrossFieldRangeTable)();
133
+ const removedCrossFieldKeys = (0, modularChangeTypes_js_1.newCrossFieldRangeTable)();
134
+ const composedRoots = composeRootTables(change1, change2, composedNodeToParent, movedCrossFieldKeys, removedCrossFieldKeys, pendingCompositions);
135
+ const crossFieldTable = newComposeTable(change1, change2, composedRoots, movedCrossFieldKeys, removedCrossFieldKeys, pendingCompositions);
124
136
  const composedFields = this.composeFieldMaps(change1.fieldChanges, change2.fieldChanges, undefined, genId, crossFieldTable, revisionMetadata);
125
137
  this.composeInvalidatedElements(crossFieldTable, composedFields, composedNodeChanges, composedNodeToParent, composedNodeAliases, genId, revisionMetadata);
126
- // Currently no field kinds require making changes to cross-field keys during composition, so we can just merge the two tables.
127
- const composedCrossFieldKeys = index_js_3.RangeMap.union(change1.crossFieldKeys, change2.crossFieldKeys);
138
+ for (const entry of crossFieldTable.renamesToDelete.entries()) {
139
+ deleteNodeRenameFrom(crossFieldTable.composedRootNodes, entry.start, entry.length);
140
+ }
141
+ for (const [nodeId, location] of crossFieldTable.movedNodeToParent.entries()) {
142
+ // Moved nodes are from change2.
143
+ // If there is a corresponding node in change1, then composedNodeToParent will already have the correct entry,
144
+ // because the location of the node is the same in change1 and the composed change
145
+ // (since they have the same input context).
146
+ if (crossFieldTable.newToBaseNodeId.get(nodeId) === undefined) {
147
+ composedNodeToParent.set(nodeId, location);
148
+ }
149
+ }
128
150
  return {
129
151
  fieldChanges: composedFields,
130
152
  nodeChanges: composedNodeChanges,
131
153
  nodeToParent: composedNodeToParent,
132
154
  nodeAliases: composedNodeAliases,
133
- crossFieldKeys: composedCrossFieldKeys,
155
+ crossFieldKeys: composeCrossFieldKeyTables(change1.crossFieldKeys, change2.crossFieldKeys, crossFieldTable.movedCrossFieldKeys, crossFieldTable.removedCrossFieldKeys),
156
+ rootNodes: composedRoots,
134
157
  };
135
158
  }
136
159
  composeInvalidatedField(fieldChange, crossFieldTable, genId, revisionMetadata) {
137
160
  const context = crossFieldTable.fieldToContext.get(fieldChange);
138
161
  (0, internal_1.assert)(context !== undefined, 0x8cc /* Should have context for every invalidated field */);
139
- const { fieldId, change1: fieldChange1, change2: fieldChange2, composedChange } = context;
162
+ const { change1: fieldChange1, change2: fieldChange2, composedChange } = context;
163
+ crossFieldTable.pendingCompositions.affectedBaseFields.delete(fieldIdKeyFromFieldId(context.fieldId));
140
164
  const rebaser = getChangeHandler(this.fieldKinds, composedChange.fieldKind).rebaser;
141
165
  const composeNodes = (child1, child2) => {
142
- if (child1 !== undefined &&
143
- child2 !== undefined &&
144
- (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(crossFieldTable.newToBaseNodeId, child2) === undefined) {
145
- (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(crossFieldTable.newToBaseNodeId, child2, child1);
146
- crossFieldTable.pendingCompositions.nodeIdsToCompose.push([child1, child2]);
166
+ if (child1 !== undefined && child2 !== undefined) {
167
+ addNodesToCompose(crossFieldTable, child1, child2);
147
168
  }
148
169
  return child1 ?? child2 ?? (0, internal_1.fail)(0xb22 /* Should not compose two undefined nodes */);
149
170
  };
150
- const amendedChange = rebaser.compose(fieldChange1, fieldChange2, composeNodes, genId, new ComposeManager(crossFieldTable, fieldChange, fieldId, false), revisionMetadata);
171
+ const amendedChange = rebaser.compose(fieldChange1, fieldChange2, composeNodes, genId, new ComposeNodeManagerI(crossFieldTable, context.fieldId, false), revisionMetadata);
151
172
  composedChange.change = (0, index_js_3.brand)(amendedChange);
152
173
  }
153
174
  /**
@@ -156,32 +177,23 @@ class ModularChangeFamily {
156
177
  * - discovering that two node changesets refer to the same node (`nodeIdsToCompose`)
157
178
  * - a previously composed field being invalidated by a cross field effect (`invalidatedFields`)
158
179
  * - a field which was copied directly from an input changeset being invalidated by a cross field effect
159
- * (`affectedBaseFields` and `affectedNewFields`)
180
+ * (`affectedBaseFields`)
160
181
  *
161
182
  * Updating an element may invalidate further elements. This function runs until there is no more invalidation.
162
183
  */
163
184
  composeInvalidatedElements(table, composedFields, composedNodes, composedNodeToParent, nodeAliases, genId, metadata) {
164
185
  const pending = table.pendingCompositions;
165
- while (table.invalidatedFields.size > 0 ||
166
- pending.nodeIdsToCompose.length > 0 ||
167
- pending.affectedBaseFields.length > 0 ||
168
- pending.affectedNewFields.length > 0) {
169
- // Note that the call to `composeNodesById` can add entries to `crossFieldTable.nodeIdPairs`.
170
- for (const [id1, id2] of pending.nodeIdsToCompose) {
171
- this.composeNodesById(table.baseChange.nodeChanges, table.newChange.nodeChanges, composedNodes, composedNodeToParent, nodeAliases, id1, id2, genId, table, metadata);
172
- }
173
- pending.nodeIdsToCompose.length = 0;
174
- this.composeAffectedFields(table, table.baseChange, true, pending.affectedBaseFields, composedFields, composedNodes, genId, metadata);
175
- this.composeAffectedFields(table, table.newChange, false, pending.affectedNewFields, composedFields, composedNodes, genId, metadata);
176
- this.processInvalidatedCompositions(table, genId, metadata);
186
+ while (pending.nodeIdsToCompose.length > 0 || pending.affectedBaseFields.length > 0) {
187
+ this.processPendingNodeCompositions(table, composedNodes, composedNodeToParent, nodeAliases, genId, metadata);
188
+ this.composeAffectedFields(table, table.baseChange, pending.affectedBaseFields, composedFields, composedNodes, genId, metadata);
177
189
  }
178
190
  }
179
- processInvalidatedCompositions(table, genId, metadata) {
180
- const fieldsToUpdate = table.invalidatedFields;
181
- table.invalidatedFields = new Set();
182
- for (const fieldChange of fieldsToUpdate) {
183
- this.composeInvalidatedField(fieldChange, table, genId, metadata);
191
+ processPendingNodeCompositions(table, composedNodes, composedNodeToParent, nodeAliases, genId, metadata) {
192
+ // Note that the call to `composeNodesById` can add entries to `crossFieldTable.nodeIdPairs`.
193
+ for (const [id1, id2] of table.pendingCompositions.nodeIdsToCompose) {
194
+ this.composeNodesById(table.baseChange, table.newChange, composedNodes, composedNodeToParent, nodeAliases, id1, id2, genId, table, metadata);
184
195
  }
196
+ table.pendingCompositions.nodeIdsToCompose.length = 0;
185
197
  }
186
198
  /**
187
199
  * Ensures that each field in `affectedFields` has been updated in the composition output.
@@ -194,38 +206,36 @@ class ModularChangeFamily {
194
206
  * If not, they are assumed to be part of the new changeset.
195
207
  * @param affectedFields - The set of fields to process.
196
208
  */
197
- composeAffectedFields(table, change, areBaseFields, affectedFields, composedFields, composedNodes, genId, metadata) {
198
- for (const fieldIdKey of affectedFields.keys()) {
199
- const fieldId = normalizeFieldId(fieldIdFromFieldIdKey(fieldIdKey), change.nodeAliases);
200
- const fieldChange = fieldChangeFromId(change.fieldChanges, change.nodeChanges, fieldId);
209
+ composeAffectedFields(table, change, affectedFields, composedFields, composedNodes, genId, metadata) {
210
+ const fieldsToProcess = affectedFields.clone();
211
+ affectedFields.clear();
212
+ for (const fieldIdKey of fieldsToProcess.keys()) {
213
+ const fieldId = fieldIdFromFieldIdKey(fieldIdKey);
214
+ const fieldChange = fieldChangeFromId(change, fieldId);
201
215
  if (table.fieldToContext.has(fieldChange) ||
202
216
  table.newFieldToBaseField.has(fieldChange)) {
203
- // This function handles fields which were not part of the intersection of the two changesets but which need to be updated anyway.
204
- // If we've already processed this field then either it is up to date
205
- // or there is pending inval which will be handled in processInvalidatedCompositions.
206
- continue;
217
+ this.composeInvalidatedField(fieldChange, table, genId, metadata);
207
218
  }
208
- const emptyChange = this.createEmptyFieldChange(fieldChange.fieldKind);
209
- const [change1, change2] = areBaseFields
210
- ? [fieldChange, emptyChange]
211
- : [emptyChange, fieldChange];
212
- const composedField = this.composeFieldChanges(fieldId, change1, change2, genId, table, metadata);
213
- if (fieldId.nodeId === undefined) {
214
- composedFields.set(fieldId.field, composedField);
215
- continue;
216
- }
217
- const nodeId = (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(table.newToBaseNodeId, fieldId.nodeId) ?? fieldId.nodeId;
218
- let nodeChangeset = nodeChangeFromId(composedNodes, nodeId);
219
- if (!table.composedNodes.has(nodeChangeset)) {
220
- nodeChangeset = cloneNodeChangeset(nodeChangeset);
221
- (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(composedNodes, nodeId, nodeChangeset);
222
- }
223
- if (nodeChangeset.fieldChanges === undefined) {
224
- nodeChangeset.fieldChanges = new Map();
219
+ else {
220
+ this.composeFieldWithNoNewChange(table, fieldChange, fieldId, composedFields, composedNodes, genId, metadata);
225
221
  }
226
- nodeChangeset.fieldChanges.set(fieldId.field, composedField);
227
222
  }
228
- affectedFields.clear();
223
+ }
224
+ composeFieldWithNoNewChange(table, baseFieldChange, fieldId, composedFields, composedNodes, genId, metadata) {
225
+ const emptyChange = this.createEmptyFieldChange(baseFieldChange.fieldKind);
226
+ const composedField = this.composeFieldChanges(fieldId, baseFieldChange, emptyChange, genId, table, metadata);
227
+ if (fieldId.nodeId === undefined) {
228
+ composedFields.set(fieldId.field, composedField);
229
+ return;
230
+ }
231
+ const nodeId = normalizeNodeId((0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(table.newToBaseNodeId, fieldId.nodeId) ?? fieldId.nodeId, table.baseChange.nodeAliases);
232
+ // We clone the node changeset before mutating it, as it may be from one of the input changesets.
233
+ const nodeChangeset = cloneNodeChangeset(nodeChangeFromId(composedNodes, table.baseChange.nodeAliases, nodeId));
234
+ (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(composedNodes, nodeId, nodeChangeset);
235
+ if (nodeChangeset.fieldChanges === undefined) {
236
+ nodeChangeset.fieldChanges = new Map();
237
+ }
238
+ nodeChangeset.fieldChanges.set(fieldId.field, composedField);
229
239
  }
230
240
  composeFieldMaps(change1, change2, parentId, genId, crossFieldTable, revisionMetadata) {
231
241
  const composedFields = new Map();
@@ -235,6 +245,14 @@ class ModularChangeFamily {
235
245
  for (const [field, fieldChange1] of change1) {
236
246
  const fieldId = { nodeId: parentId, field };
237
247
  const fieldChange2 = change2.get(field);
248
+ const cachedComposedFieldChange = crossFieldTable.fieldToContext.get(fieldChange1)?.composedChange;
249
+ if (fieldChange2 === undefined && cachedComposedFieldChange !== undefined) {
250
+ // This can happen if the field was previous processed in `composeFieldWithNoNewChange`.
251
+ // If `change2` does not have a change for this field, then without this check we would
252
+ // lose the composed field change and instead simply have `change1`'s change.
253
+ composedFields.set(field, cachedComposedFieldChange);
254
+ continue;
255
+ }
238
256
  const composedField = fieldChange2 === undefined
239
257
  ? fieldChange1
240
258
  : this.composeFieldChanges(fieldId, fieldChange1, fieldChange2, genId, crossFieldTable, revisionMetadata);
@@ -254,17 +272,16 @@ class ModularChangeFamily {
254
272
  * will be added to `crossFieldTable.pendingCompositions.nodeIdsToCompose`.
255
273
  *
256
274
  * Any fields which had cross-field information sent to them as part of this field composition
257
- * will be added to either `affectedBaseFields` or `affectedNewFields` in `crossFieldTable.pendingCompositions`.
275
+ * will be added to `affectedBaseFields` in `crossFieldTable.pendingCompositions`.
258
276
  *
259
277
  * Any composed `FieldChange` which is invalidated by new cross-field information will be added to `crossFieldTable.invalidatedFields`.
260
278
  */
261
279
  composeFieldChanges(fieldId, change1, change2, idAllocator, crossFieldTable, revisionMetadata) {
262
280
  const { fieldKind, changeHandler, change1: change1Normalized, change2: change2Normalized, } = this.normalizeFieldChanges(change1, change2);
263
- const manager = new ComposeManager(crossFieldTable, change1, fieldId);
281
+ const manager = new ComposeNodeManagerI(crossFieldTable, fieldId);
264
282
  const composedChange = changeHandler.rebaser.compose(change1Normalized, change2Normalized, (child1, child2) => {
265
283
  if (child1 !== undefined && child2 !== undefined) {
266
- (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(crossFieldTable.newToBaseNodeId, child2, child1);
267
- crossFieldTable.pendingCompositions.nodeIdsToCompose.push([child1, child2]);
284
+ addNodesToCompose(crossFieldTable, child1, child2);
268
285
  }
269
286
  return child1 ?? child2 ?? (0, internal_1.fail)(0xb23 /* Should not compose two undefined nodes */);
270
287
  }, idAllocator, manager, revisionMetadata);
@@ -281,19 +298,18 @@ class ModularChangeFamily {
281
298
  crossFieldTable.newFieldToBaseField.set(change2, change1);
282
299
  return composedField;
283
300
  }
284
- composeNodesById(nodeChanges1, nodeChanges2, composedNodes, composedNodeToParent, nodeAliases, id1, id2, idAllocator, crossFieldTable, revisionMetadata) {
285
- const nodeChangeset1 = nodeChangeFromId(nodeChanges1, id1);
286
- const nodeChangeset2 = nodeChangeFromId(nodeChanges2, id2);
301
+ composeNodesById(change1, change2, composedNodes, composedNodeToParent, composedAliases, id1, id2, idAllocator, crossFieldTable, revisionMetadata) {
302
+ const nodeChangeset1 = nodeChangeFromId(change1.nodeChanges, change1.nodeAliases, id1);
303
+ const nodeChangeset2 = nodeChangeFromId(change2.nodeChanges, change2.nodeAliases, id2);
287
304
  const composedNodeChangeset = this.composeNodeChanges(id1, nodeChangeset1, nodeChangeset2, idAllocator, crossFieldTable, revisionMetadata);
288
305
  (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(composedNodes, id1, composedNodeChangeset);
289
306
  if (!(0, index_js_2.areEqualChangeAtomIds)(id1, id2)) {
290
307
  composedNodes.delete([id2.revision, id2.localId]);
291
308
  composedNodeToParent.delete([id2.revision, id2.localId]);
292
- (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(nodeAliases, id2, id1);
309
+ (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(composedAliases, id2, id1);
293
310
  // We need to delete id1 to avoid forming a cycle in case id1 already had an alias.
294
- nodeAliases.delete([id1.revision, id1.localId]);
311
+ composedAliases.delete([id1.revision, id1.localId]);
295
312
  }
296
- crossFieldTable.composedNodes.add(composedNodeChangeset);
297
313
  }
298
314
  composeNodeChanges(nodeId, change1, change2, genId, crossFieldTable, revisionMetadata) {
299
315
  // WARNING: this composition logic assumes that we never make compositions of the following form:
@@ -346,9 +362,14 @@ class ModularChangeFamily {
346
362
  }
347
363
  const genId = (0, index_js_3.idAllocatorFromMaxId)(change.change.maxId ?? -1);
348
364
  const crossFieldTable = {
349
- ...newCrossFieldTable(),
365
+ change: change.change,
366
+ entries: (0, index_js_2.newChangeAtomIdRangeMap)(),
350
367
  originalFieldToContext: new Map(),
368
+ invertRevision: revisionForInvert,
351
369
  invertedNodeToParent: (0, index_js_3.brand)(change.change.nodeToParent.clone()),
370
+ invalidatedFields: new Set(),
371
+ invertedRoots: invertRootTable(change.change, isRollback),
372
+ attachToDetachId: (0, index_js_2.newChangeAtomIdTransform)(),
352
373
  };
353
374
  const { revInfos: oldRevInfos } = getRevInfoFromTaggedChanges([change]);
354
375
  const revisionMetadata = (0, index_js_2.revisionMetadataSourceFromInfo)(oldRevInfos);
@@ -364,16 +385,18 @@ class ModularChangeFamily {
364
385
  const originalFieldChange = fieldChange.change;
365
386
  const context = crossFieldTable.originalFieldToContext.get(fieldChange);
366
387
  (0, internal_1.assert)(context !== undefined, 0x851 /* Should have context for every invalidated field */);
367
- const { invertedField, fieldId } = context;
368
- const amendedChange = getChangeHandler(this.fieldKinds, fieldChange.fieldKind).rebaser.invert(originalFieldChange, isRollback, genId, revisionForInvert, new InvertManager(crossFieldTable, fieldChange, fieldId), revisionMetadata);
388
+ const { invertedField } = context;
389
+ const amendedChange = getChangeHandler(this.fieldKinds, fieldChange.fieldKind).rebaser.invert(originalFieldChange, isRollback, genId, revisionForInvert, new InvertNodeManagerI(crossFieldTable, context.fieldId), revisionMetadata);
369
390
  invertedField.change = (0, index_js_3.brand)(amendedChange);
370
391
  }
371
392
  }
372
393
  const crossFieldKeys = this.makeCrossFieldKeyTable(invertedFields, invertedNodes);
394
+ this.processInvertRenames(crossFieldTable);
373
395
  return makeModularChangeset({
374
396
  fieldChanges: invertedFields,
375
397
  nodeChanges: invertedNodes,
376
398
  nodeToParent: crossFieldTable.invertedNodeToParent,
399
+ rootNodes: crossFieldTable.invertedRoots,
377
400
  nodeAliases: change.change.nodeAliases,
378
401
  crossFieldKeys,
379
402
  maxId: genId.getMaxId(),
@@ -389,7 +412,7 @@ class ModularChangeFamily {
389
412
  const invertedFields = new Map();
390
413
  for (const [field, fieldChange] of changes) {
391
414
  const fieldId = { nodeId: parentId, field };
392
- const manager = new InvertManager(crossFieldTable, fieldChange, fieldId);
415
+ const manager = new InvertNodeManagerI(crossFieldTable, fieldId);
393
416
  const invertedChange = getChangeHandler(this.fieldKinds, fieldChange.fieldKind).rebaser.invert(fieldChange.change, isRollback, genId, revisionForInvert, manager, revisionMetadata);
394
417
  const invertedFieldChange = {
395
418
  ...fieldChange,
@@ -421,6 +444,12 @@ class ModularChangeFamily {
421
444
  }
422
445
  return inverse;
423
446
  }
447
+ processInvertRenames(table) {
448
+ for (const { start: newAttachId, value: originalDetachId, length, } of table.attachToDetachId.entries()) {
449
+ // Note that the detach location is already set in `invertDetach`.
450
+ addNodeRename(table.invertedRoots, originalDetachId, newAttachId, length, undefined);
451
+ }
452
+ }
424
453
  rebase(taggedChange, potentiallyConflictedOver, revisionMetadata) {
425
454
  // Our current cell ordering scheme in sequences depends on being able to rebase over a change with conflicts.
426
455
  // This means that we must rebase over a muted version of the conflicted changeset.
@@ -431,17 +460,26 @@ class ModularChangeFamily {
431
460
  const maxId = Math.max(change.maxId ?? -1, over.change.maxId ?? -1);
432
461
  const idState = { maxId };
433
462
  const genId = (0, index_js_3.idAllocatorFromState)(idState);
463
+ const affectedBaseFields = (0, index_js_3.newTupleBTree)();
464
+ const nodesToRebase = [];
465
+ const rebasedNodeToParent = (0, index_js_3.brand)(change.nodeToParent.clone());
466
+ const rebaseVersion = Math.max(change.rebaseVersion, over.change.rebaseVersion);
467
+ const rebasedRootNodes = rebaseRoots(change, over.change, affectedBaseFields, nodesToRebase, rebasedNodeToParent, rebaseVersion);
434
468
  const crossFieldTable = {
435
- ...newCrossFieldTable(),
469
+ rebaseVersion,
470
+ entries: newDetachedEntryMap(),
436
471
  newChange: change,
437
472
  baseChange: over.change,
438
473
  baseFieldToContext: new Map(),
474
+ baseRoots: over.change.rootNodes,
475
+ rebasedRootNodes,
439
476
  baseToRebasedNodeId: (0, index_js_3.newTupleBTree)(),
440
477
  rebasedFields: new Set(),
441
- rebasedNodeToParent: (0, index_js_3.brand)(change.nodeToParent.clone()),
442
- rebasedCrossFieldKeys: change.crossFieldKeys.clone(),
478
+ rebasedNodeToParent,
479
+ rebasedDetachLocations: (0, index_js_2.newChangeAtomIdRangeMap)(),
480
+ movedDetaches: (0, index_js_2.newChangeAtomIdRangeMap)(),
443
481
  nodeIdPairs: [],
444
- affectedBaseFields: (0, index_js_3.newTupleBTree)(),
482
+ affectedBaseFields,
445
483
  fieldsWithUnattachedChild: new Set(),
446
484
  };
447
485
  const getBaseRevisions = () => revisionInfoFromTaggedChange(over).map((info) => info.revision);
@@ -451,8 +489,9 @@ class ModularChangeFamily {
451
489
  getBaseRevisions,
452
490
  };
453
491
  const rebasedNodes = (0, index_js_3.brand)(change.nodeChanges.clone());
454
- const rebasedFields = this.rebaseIntersectingFields(crossFieldTable, rebasedNodes, genId, rebaseMetadata);
455
- this.rebaseInvalidatedElements(rebasedFields, rebasedNodes, crossFieldTable, rebaseMetadata, genId);
492
+ const rebasedFields = this.rebaseIntersectingFields(nodesToRebase, crossFieldTable, rebasedNodes, genId, rebaseMetadata);
493
+ this.rebaseInvalidatedFields(rebasedFields, rebasedNodes, crossFieldTable, rebaseMetadata, genId);
494
+ fixupRebasedDetachLocations(crossFieldTable);
456
495
  const constraintState = newConstraintState(change.constraintViolationCount ?? 0);
457
496
  const revertConstraintState = newConstraintState(change.constraintViolationCountOnRevert ?? 0);
458
497
  let noChangeConstraint = change.noChangeConstraint;
@@ -460,13 +499,17 @@ class ModularChangeFamily {
460
499
  noChangeConstraint = { violated: true };
461
500
  constraintState.violationCount += 1;
462
501
  }
463
- this.updateConstraintsForFields(rebasedFields, fieldChangeHandler_js_1.NodeAttachState.Attached, fieldChangeHandler_js_1.NodeAttachState.Attached, constraintState, revertConstraintState, rebasedNodes);
502
+ this.updateConstraints(rebasedFields, rebasedNodes, rebasedRootNodes, constraintState, revertConstraintState);
503
+ const fieldsWithRootMoves = getFieldsWithRootMoves(crossFieldTable.rebasedRootNodes, change.nodeAliases);
504
+ const fieldToRootChanges = getFieldToRootChanges(crossFieldTable.rebasedRootNodes, change.nodeAliases);
464
505
  const rebased = makeModularChangeset({
465
- fieldChanges: this.pruneFieldMap(rebasedFields, rebasedNodes),
506
+ fieldChanges: this.pruneFieldMap(rebasedFields, undefined, rebasedNodes, crossFieldTable.rebasedNodeToParent, change.nodeAliases, crossFieldTable.rebasedRootNodes, fieldsWithRootMoves, fieldToRootChanges),
466
507
  nodeChanges: rebasedNodes,
467
508
  nodeToParent: crossFieldTable.rebasedNodeToParent,
509
+ rootNodes: this.pruneRoots(crossFieldTable.rebasedRootNodes, rebasedNodes, crossFieldTable.rebasedNodeToParent, change.nodeAliases, fieldsWithRootMoves, fieldToRootChanges),
510
+ // TODO: Do we need to include aliases for node changesets added during rebasing?
468
511
  nodeAliases: change.nodeAliases,
469
- crossFieldKeys: crossFieldTable.rebasedCrossFieldKeys,
512
+ crossFieldKeys: rebaseCrossFieldKeys(change.crossFieldKeys, crossFieldTable.movedDetaches, crossFieldTable.rebasedDetachLocations),
470
513
  maxId: idState.maxId,
471
514
  revisions: change.revisions,
472
515
  constraintViolationCount: constraintState.violationCount,
@@ -476,15 +519,22 @@ class ModularChangeFamily {
476
519
  builds: change.builds,
477
520
  destroys: change.destroys,
478
521
  refreshers: change.refreshers,
522
+ rebaseVersion,
479
523
  });
524
+ // XXX: This is an expensive assert which should be disabled before merging.
525
+ validateChangeset(rebased, this.fieldKinds);
480
526
  return rebased;
481
527
  }
482
528
  // This performs a first pass on all fields which have both new and base changes.
483
529
  // TODO: Can we also handle additional passes in this method?
484
- rebaseIntersectingFields(crossFieldTable, rebasedNodes, genId, metadata) {
530
+ rebaseIntersectingFields(rootChanges, crossFieldTable, rebasedNodes, genId, metadata) {
485
531
  const change = crossFieldTable.newChange;
486
532
  const baseChange = crossFieldTable.baseChange;
487
533
  const rebasedFields = this.rebaseFieldMap(change.fieldChanges, baseChange.fieldChanges, undefined, genId, crossFieldTable, metadata);
534
+ for (const [newChildChange, baseChildChange] of rootChanges) {
535
+ const rebasedNode = this.rebaseNodeChange(newChildChange, baseChildChange, genId, crossFieldTable, metadata);
536
+ (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(rebasedNodes, newChildChange, rebasedNode);
537
+ }
488
538
  // This loop processes all fields which have both base and new changes.
489
539
  // Note that the call to `rebaseNodeChange` can add entries to `crossFieldTable.nodeIdPairs`.
490
540
  for (const [newId, baseId, _attachState] of crossFieldTable.nodeIdPairs) {
@@ -493,87 +543,85 @@ class ModularChangeFamily {
493
543
  }
494
544
  return rebasedFields;
495
545
  }
496
- // This processes fields which have no new changes but have been invalidated by another field.
497
- rebaseFieldsWithoutNewChanges(rebasedFields, rebasedNodes, crossFieldTable, genId, metadata) {
498
- const baseChange = crossFieldTable.baseChange;
499
- for (const [revision, localId, fieldKey] of crossFieldTable.affectedBaseFields.keys()) {
500
- const baseNodeId = localId === undefined
501
- ? undefined
502
- : normalizeNodeId({ revision, localId }, baseChange.nodeAliases);
503
- const baseFieldChange = fieldMapFromNodeId(baseChange.fieldChanges, baseChange.nodeChanges, baseNodeId).get(fieldKey);
504
- (0, internal_1.assert)(baseFieldChange !== undefined, 0x9c2 /* Cross field key registered for empty field */);
505
- if (crossFieldTable.baseFieldToContext.has(baseFieldChange)) {
506
- // This field has already been processed because there were changes to rebase.
507
- continue;
508
- }
509
- // This field has no changes in the new changeset, otherwise it would have been added to
510
- // `crossFieldTable.baseFieldToContext` when processing fields with both base and new changes.
511
- const rebaseChild = (child, baseChild, stateChange) => {
512
- (0, internal_1.assert)(child === undefined, 0x9c3 /* There should be no new changes in this field */);
546
+ rebaseFieldWithoutNewChanges(baseFieldChange, baseFieldId, crossFieldTable, rebasedFields, rebasedNodes, genId, metadata,
547
+ /**
548
+ * The ID of a node in `baseFieldChange` which should be included in the rebased field change.
549
+ */
550
+ baseNodeId) {
551
+ // This field has no changes in the new changeset, otherwise it would have been added to
552
+ // `crossFieldTable.baseFieldToContext` when processing fields with both base and new changes.
553
+ const rebaseChild = (child, baseChild, stateChange) => {
554
+ (0, internal_1.assert)(child === undefined, 0x9c3 /* There should be no new changes in this field */);
555
+ if (baseChild === undefined || baseNodeId === undefined) {
513
556
  return undefined;
514
- };
515
- const handler = getChangeHandler(this.fieldKinds, baseFieldChange.fieldKind);
516
- const fieldChange = {
517
- ...baseFieldChange,
518
- change: (0, index_js_3.brand)(handler.createEmpty()),
519
- };
520
- const rebasedNodeId = baseNodeId === undefined
521
- ? undefined
522
- : rebasedNodeIdFromBaseNodeId(crossFieldTable, baseNodeId);
523
- const fieldId = { nodeId: rebasedNodeId, field: fieldKey };
524
- const rebasedField = handler.rebaser.rebase(fieldChange.change, baseFieldChange.change, rebaseChild, genId, new RebaseManager(crossFieldTable, baseFieldChange, fieldId), metadata);
525
- const rebasedFieldChange = {
526
- ...baseFieldChange,
527
- change: (0, index_js_3.brand)(rebasedField),
528
- };
529
- // TODO: Deduplicate
530
- crossFieldTable.baseFieldToContext.set(baseFieldChange, {
531
- newChange: fieldChange,
532
- baseChange: baseFieldChange,
533
- rebasedChange: rebasedFieldChange,
534
- fieldId,
535
- baseNodeIds: [],
536
- });
537
- crossFieldTable.rebasedFields.add(rebasedFieldChange);
538
- this.attachRebasedField(rebasedFields, rebasedNodes, crossFieldTable, rebasedFieldChange, fieldId, genId, metadata);
539
- }
540
- }
541
- rebaseInvalidatedElements(rebasedFields, rebasedNodes, table, metadata, idAllocator) {
542
- this.rebaseFieldsWithoutNewChanges(rebasedFields, rebasedNodes, table, idAllocator, metadata);
543
- this.rebaseFieldsWithUnattachedChild(table, metadata, idAllocator);
544
- this.rebaseInvalidatedFields(table, metadata, idAllocator);
545
- }
546
- rebaseInvalidatedFields(crossFieldTable, rebaseMetadata, genId) {
547
- const fieldsToUpdate = crossFieldTable.invalidatedFields;
548
- crossFieldTable.invalidatedFields = new Set();
549
- for (const field of fieldsToUpdate) {
550
- this.rebaseInvalidatedField(field, crossFieldTable, rebaseMetadata, genId);
551
- }
552
- }
553
- rebaseFieldsWithUnattachedChild(table, metadata, idAllocator) {
554
- for (const field of table.fieldsWithUnattachedChild) {
555
- table.invalidatedFields.delete(field);
556
- this.rebaseInvalidatedField(field, table, metadata, idAllocator, true);
557
+ }
558
+ return (0, index_js_2.areEqualChangeAtomIds)(normalizeNodeId(baseChild, crossFieldTable.baseChange.nodeAliases), baseNodeId)
559
+ ? baseNodeId
560
+ : undefined;
561
+ };
562
+ const handler = getChangeHandler(this.fieldKinds, baseFieldChange.fieldKind);
563
+ const fieldChange = {
564
+ ...baseFieldChange,
565
+ change: (0, index_js_3.brand)(handler.createEmpty()),
566
+ };
567
+ const rebasedNodeId = baseFieldId.nodeId === undefined
568
+ ? undefined
569
+ : rebasedNodeIdFromBaseNodeId(crossFieldTable, baseFieldId.nodeId);
570
+ const fieldId = { nodeId: rebasedNodeId, field: baseFieldId.field };
571
+ const rebasedField = handler.rebaser.rebase(fieldChange.change, baseFieldChange.change, rebaseChild, genId, new RebaseNodeManagerI(crossFieldTable, fieldId), metadata, crossFieldTable.rebaseVersion);
572
+ const rebasedFieldChange = {
573
+ ...baseFieldChange,
574
+ change: (0, index_js_3.brand)(rebasedField),
575
+ };
576
+ const context = {
577
+ newChange: fieldChange,
578
+ baseChange: baseFieldChange,
579
+ rebasedChange: rebasedFieldChange,
580
+ fieldId,
581
+ baseNodeIds: (0, index_js_3.newTupleBTree)(),
582
+ };
583
+ if (baseNodeId !== undefined) {
584
+ (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(context.baseNodeIds, baseNodeId, true);
585
+ }
586
+ crossFieldTable.baseFieldToContext.set(baseFieldChange, context);
587
+ crossFieldTable.rebasedFields.add(rebasedFieldChange);
588
+ this.attachRebasedField(rebasedFields, rebasedNodes, crossFieldTable, rebasedFieldChange, fieldId, genId, metadata);
589
+ }
590
+ rebaseInvalidatedFields(rebasedFields, rebasedNodes, crossFieldTable, rebaseMetadata, genId) {
591
+ while (crossFieldTable.affectedBaseFields.size > 0) {
592
+ const baseFields = crossFieldTable.affectedBaseFields.clone();
593
+ crossFieldTable.affectedBaseFields.clear();
594
+ for (const baseFieldIdKey of baseFields.keys()) {
595
+ const baseFieldId = normalizeFieldId(fieldIdFromFieldIdKey(baseFieldIdKey), crossFieldTable.baseChange.nodeAliases);
596
+ const baseField = fieldChangeFromId(crossFieldTable.baseChange, baseFieldId);
597
+ (0, internal_1.assert)(baseField !== undefined, 0x9c2 /* Cross field key registered for empty field */);
598
+ const context = crossFieldTable.baseFieldToContext.get(baseField);
599
+ if (context === undefined) {
600
+ this.rebaseFieldWithoutNewChanges(baseField, baseFieldId, crossFieldTable, rebasedFields, rebasedNodes, genId, rebaseMetadata);
601
+ }
602
+ else {
603
+ this.rebaseInvalidatedField(baseField, crossFieldTable, context, rebaseMetadata, genId);
604
+ }
605
+ }
557
606
  }
558
607
  }
559
- rebaseInvalidatedField(baseField, crossFieldTable, rebaseMetadata, genId, allowInval = false) {
560
- const context = crossFieldTable.baseFieldToContext.get(baseField);
561
- (0, internal_1.assert)(context !== undefined, 0x852 /* Every field should have a context */);
608
+ rebaseInvalidatedField(baseField, crossFieldTable, context, rebaseMetadata, genId) {
562
609
  const { changeHandler, change1: fieldChangeset, change2: baseChangeset, } = this.normalizeFieldChanges(context.newChange, context.baseChange);
563
610
  const rebaseChild = (curr, base) => {
564
611
  if (curr !== undefined) {
565
612
  return curr;
566
613
  }
567
- if (base !== undefined) {
568
- for (const id of context.baseNodeIds) {
569
- if ((0, index_js_2.areEqualChangeAtomIds)(base, id)) {
570
- return base;
571
- }
572
- }
614
+ if (base !== undefined && (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(context.baseNodeIds, base) === true) {
615
+ return base;
573
616
  }
574
617
  return undefined;
575
618
  };
576
- context.rebasedChange.change = (0, index_js_3.brand)(changeHandler.rebaser.rebase(fieldChangeset, baseChangeset, rebaseChild, genId, new RebaseManager(crossFieldTable, baseField, context.fieldId, allowInval), rebaseMetadata));
619
+ let allowInval = false;
620
+ if (crossFieldTable.fieldsWithUnattachedChild.has(baseField)) {
621
+ crossFieldTable.fieldsWithUnattachedChild.delete(baseField);
622
+ allowInval = true;
623
+ }
624
+ context.rebasedChange.change = (0, index_js_3.brand)(changeHandler.rebaser.rebase(fieldChangeset, baseChangeset, rebaseChild, genId, new RebaseNodeManagerI(crossFieldTable, context.fieldId, allowInval), rebaseMetadata, crossFieldTable.rebaseVersion));
577
625
  }
578
626
  attachRebasedField(rebasedFields, rebasedNodes, table, rebasedField, { nodeId, field: fieldKey }, idAllocator, metadata) {
579
627
  if (nodeId === undefined) {
@@ -582,12 +630,14 @@ class ModularChangeFamily {
582
630
  }
583
631
  const rebasedNode = (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(rebasedNodes, nodeId);
584
632
  if (rebasedNode !== undefined) {
585
- if (rebasedNode.fieldChanges === undefined) {
586
- rebasedNode.fieldChanges = new Map([[fieldKey, rebasedField]]);
633
+ const updatedRebasedNode = cloneNodeChangeset(rebasedNode);
634
+ (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(rebasedNodes, nodeId, updatedRebasedNode);
635
+ if (updatedRebasedNode.fieldChanges === undefined) {
636
+ updatedRebasedNode.fieldChanges = new Map([[fieldKey, rebasedField]]);
587
637
  return;
588
638
  }
589
- (0, internal_1.assert)(!rebasedNode.fieldChanges.has(fieldKey), 0x9c4 /* Expected an empty field */);
590
- rebasedNode.fieldChanges.set(fieldKey, rebasedField);
639
+ (0, internal_1.assert)(!updatedRebasedNode.fieldChanges.has(fieldKey), 0x9c4 /* Expected an empty field */);
640
+ updatedRebasedNode.fieldChanges.set(fieldKey, rebasedField);
591
641
  return;
592
642
  }
593
643
  const newNode = {
@@ -595,39 +645,51 @@ class ModularChangeFamily {
595
645
  };
596
646
  (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(rebasedNodes, nodeId, newNode);
597
647
  (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(table.baseToRebasedNodeId, nodeId, nodeId);
598
- const parentFieldId = getParentFieldId(table.baseChange, nodeId);
599
- this.attachRebasedNode(rebasedFields, rebasedNodes, table, nodeId, parentFieldId, idAllocator, metadata);
600
- }
601
- attachRebasedNode(rebasedFields, rebasedNodes, table, baseNodeId, parentFieldIdBase, idAllocator, metadata) {
602
- const baseFieldChange = fieldChangeFromId(table.baseChange.fieldChanges, table.baseChange.nodeChanges, parentFieldIdBase);
648
+ const parentBase = getNodeParent(table.baseChange, nodeId);
649
+ this.attachRebasedNode(rebasedFields, rebasedNodes, table, nodeId, parentBase, idAllocator, metadata);
650
+ }
651
+ attachRebasedNode(rebasedFields, rebasedNodes, table, baseNodeId, parentBase, idAllocator, metadata) {
652
+ if (parentBase.root !== undefined) {
653
+ const renamedRoot = firstAttachIdFromDetachId(table.baseChange.rootNodes, parentBase.root, 1).value;
654
+ const attachField = table.baseChange.crossFieldKeys.getFirst({ ...renamedRoot, target: crossFieldQueries_js_1.CrossFieldTarget.Destination }, 1).value;
655
+ if (attachField === undefined) {
656
+ const baseDetachLocation = table.baseChange.rootNodes.detachLocations.getFirst(parentBase.root, 1).value;
657
+ assignRootChange(table.rebasedRootNodes, table.rebasedNodeToParent, renamedRoot, baseNodeId, baseDetachLocation, table.rebaseVersion);
658
+ // We need to make sure the rebased changeset includes the detach location,
659
+ // so we add that field to `affectedBaseFields` unless it's already been processed.
660
+ if (baseDetachLocation !== undefined &&
661
+ !table.baseFieldToContext.has(fieldChangeFromId(table.baseChange, baseDetachLocation))) {
662
+ table.affectedBaseFields.set(fieldIdKeyFromFieldId(baseDetachLocation), true);
663
+ }
664
+ }
665
+ else {
666
+ // The base change inserts this node into `attachField`, so the rebased change should represent this node there.
667
+ const normalizedAttachField = normalizeFieldId(attachField, table.baseChange.nodeAliases);
668
+ const entry = table.entries.getFirst(renamedRoot, 1).value ?? {};
669
+ table.entries.set(renamedRoot, 1, { ...entry, nodeChange: baseNodeId });
670
+ table.affectedBaseFields.set(fieldIdKeyFromFieldId(normalizedAttachField), true);
671
+ this.attachRebasedNode(rebasedFields, rebasedNodes, table, baseNodeId, { field: normalizedAttachField }, idAllocator, metadata);
672
+ }
673
+ return;
674
+ }
675
+ const parentFieldIdBase = parentBase.field;
676
+ const baseFieldChange = fieldChangeFromId(table.baseChange, parentFieldIdBase);
603
677
  const rebasedFieldId = rebasedFieldIdFromBaseId(table, parentFieldIdBase);
604
- (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(table.rebasedNodeToParent, baseNodeId, rebasedFieldId);
678
+ (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(table.rebasedNodeToParent, baseNodeId, { field: rebasedFieldId });
605
679
  const context = table.baseFieldToContext.get(baseFieldChange);
606
680
  if (context !== undefined) {
607
681
  // We've already processed this field.
608
- // The new child node will be attached in rebaseFieldsWithUnattachedChild.
609
- context.baseNodeIds.push(baseNodeId);
610
- table.fieldsWithUnattachedChild.add(baseFieldChange);
682
+ // The new child node will be attached in the next pass.
683
+ // Note that adding to `fieldsWithUnattachedChild` allows that field to generate new invalidations,
684
+ // so to avoid invalidation cycles we make sure we only add to it once per new unattached child.
685
+ // This is done by checking whether `context.baseNodeIds` already contained `baseNodeId`.
686
+ if ((0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(context.baseNodeIds, baseNodeId, true)) {
687
+ table.fieldsWithUnattachedChild.add(baseFieldChange);
688
+ table.affectedBaseFields.set(fieldIdKeyFromFieldId(parentFieldIdBase), true);
689
+ }
611
690
  return;
612
691
  }
613
- const handler = getChangeHandler(this.fieldKinds, baseFieldChange.fieldKind);
614
- const fieldChange = {
615
- ...baseFieldChange,
616
- change: (0, index_js_3.brand)(handler.createEmpty()),
617
- };
618
- const rebasedChangeset = handler.rebaser.rebase(handler.createEmpty(), baseFieldChange.change, (_idNew, idBase) => idBase !== undefined && (0, index_js_2.areEqualChangeAtomIds)(idBase, baseNodeId)
619
- ? baseNodeId
620
- : undefined, idAllocator, new RebaseManager(table, baseFieldChange, rebasedFieldId), metadata);
621
- const rebasedField = { ...baseFieldChange, change: (0, index_js_3.brand)(rebasedChangeset) };
622
- table.rebasedFields.add(rebasedField);
623
- table.baseFieldToContext.set(baseFieldChange, {
624
- newChange: fieldChange,
625
- baseChange: baseFieldChange,
626
- rebasedChange: rebasedField,
627
- fieldId: rebasedFieldId,
628
- baseNodeIds: [],
629
- });
630
- this.attachRebasedField(rebasedFields, rebasedNodes, table, rebasedField, rebasedFieldId, idAllocator, metadata);
692
+ this.rebaseFieldWithoutNewChanges(baseFieldChange, parentFieldIdBase, table, rebasedFields, rebasedNodes, idAllocator, metadata, baseNodeId);
631
693
  }
632
694
  rebaseFieldMap(change, over, parentId, genId, crossFieldTable, revisionMetadata) {
633
695
  const rebasedFields = new Map();
@@ -645,8 +707,8 @@ class ModularChangeFamily {
645
707
  continue;
646
708
  }
647
709
  const { fieldKind, changeHandler, change1: fieldChangeset, change2: baseChangeset, } = this.normalizeFieldChanges(fieldChange, baseChange);
648
- const manager = new RebaseManager(crossFieldTable, baseChange, fieldId);
649
- const rebasedField = changeHandler.rebaser.rebase(fieldChangeset, baseChangeset, rebaseChild, genId, manager, revisionMetadata);
710
+ const manager = new RebaseNodeManagerI(crossFieldTable, fieldId);
711
+ const rebasedField = changeHandler.rebaser.rebase(fieldChangeset, baseChangeset, rebaseChild, genId, manager, revisionMetadata, crossFieldTable.rebaseVersion);
650
712
  const rebasedFieldChange = {
651
713
  fieldKind,
652
714
  change: (0, index_js_3.brand)(rebasedField),
@@ -657,15 +719,15 @@ class ModularChangeFamily {
657
719
  newChange: fieldChange,
658
720
  rebasedChange: rebasedFieldChange,
659
721
  fieldId,
660
- baseNodeIds: [],
722
+ baseNodeIds: (0, index_js_3.newTupleBTree)(),
661
723
  });
662
724
  crossFieldTable.rebasedFields.add(rebasedFieldChange);
663
725
  }
664
726
  return rebasedFields;
665
727
  }
666
728
  rebaseNodeChange(newId, baseId, genId, crossFieldTable, revisionMetadata) {
667
- const change = nodeChangeFromId(crossFieldTable.newChange.nodeChanges, newId);
668
- const over = nodeChangeFromId(crossFieldTable.baseChange.nodeChanges, baseId);
729
+ const change = nodeChangeFromId(crossFieldTable.newChange.nodeChanges, crossFieldTable.newChange.nodeAliases, newId);
730
+ const over = nodeChangeFromId(crossFieldTable.baseChange.nodeChanges, crossFieldTable.baseChange.nodeAliases, baseId);
669
731
  const baseMap = over?.fieldChanges ?? new Map();
670
732
  const fieldChanges = change.fieldChanges !== undefined && over.fieldChanges !== undefined
671
733
  ? this.rebaseFieldMap(change?.fieldChanges ?? new Map(), baseMap, newId, genId, crossFieldTable, revisionMetadata)
@@ -683,28 +745,37 @@ class ModularChangeFamily {
683
745
  (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(crossFieldTable.baseToRebasedNodeId, baseId, newId);
684
746
  return rebasedChange;
685
747
  }
748
+ updateConstraints(rebasedFields, rebasedNodes, rebasedRoots, constraintState, revertConstraintState) {
749
+ this.updateConstraintsForFields(rebasedFields, fieldChangeHandler_js_1.NodeAttachState.Attached, fieldChangeHandler_js_1.NodeAttachState.Attached, constraintState, revertConstraintState, rebasedNodes);
750
+ for (const [_detachId, nodeId] of rebasedRoots.nodeChanges.entries()) {
751
+ // XXX: This is incorrect if the rebased changeset attaches the node.
752
+ // Efficiently computing whether the changeset attaches the node would require maintaining a mapping from node ID to attach ID.
753
+ const detachedInOutput = true;
754
+ this.updateConstraintsForNode(nodeId, fieldChangeHandler_js_1.NodeAttachState.Detached, detachedInOutput ? fieldChangeHandler_js_1.NodeAttachState.Detached : fieldChangeHandler_js_1.NodeAttachState.Attached, rebasedNodes, constraintState, revertConstraintState);
755
+ }
756
+ }
686
757
  updateConstraintsForFields(fields, parentInputAttachState, parentOutputAttachState, constraintState, revertConstraintState, nodes) {
687
758
  for (const field of fields.values()) {
688
759
  const handler = getChangeHandler(this.fieldKinds, field.fieldKind);
689
- for (const [nodeId, inputIndex, outputIndex] of handler.getNestedChanges(field.change)) {
690
- const isInputDetached = inputIndex === undefined;
691
- const inputAttachState = parentInputAttachState === fieldChangeHandler_js_1.NodeAttachState.Detached || isInputDetached
692
- ? fieldChangeHandler_js_1.NodeAttachState.Detached
693
- : fieldChangeHandler_js_1.NodeAttachState.Attached;
694
- const isOutputDetached = outputIndex === undefined;
760
+ for (const [nodeId] of handler.getNestedChanges(field.change)) {
761
+ // XXX: This is incorrect if the rebased changeset detaches this node.
762
+ // Efficiently computing whether the changeset detaches the node would require maintaining a mapping from node ID to detach ID.
763
+ const isOutputDetached = false;
695
764
  const outputAttachState = parentOutputAttachState === fieldChangeHandler_js_1.NodeAttachState.Detached || isOutputDetached
696
765
  ? fieldChangeHandler_js_1.NodeAttachState.Detached
697
766
  : fieldChangeHandler_js_1.NodeAttachState.Attached;
698
- this.updateConstraintsForNode(nodeId, inputAttachState, outputAttachState, nodes, constraintState, revertConstraintState);
767
+ this.updateConstraintsForNode(nodeId, parentInputAttachState, outputAttachState, nodes, constraintState, revertConstraintState);
699
768
  }
700
769
  }
701
770
  }
702
771
  updateConstraintsForNode(nodeId, inputAttachState, outputAttachState, nodes, constraintState, revertConstraintState) {
703
- const node = nodes.get([nodeId.revision, nodeId.localId]) ?? (0, internal_1.fail)(0xb24 /* Unknown node ID */);
772
+ const node = (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(nodes, nodeId) ?? (0, internal_1.fail)(0xb24 /* Unknown node ID */);
773
+ const updatedNode = { ...node };
774
+ (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(nodes, nodeId, updatedNode);
704
775
  if (node.nodeExistsConstraint !== undefined) {
705
776
  const isNowViolated = inputAttachState === fieldChangeHandler_js_1.NodeAttachState.Detached;
706
777
  if (node.nodeExistsConstraint.violated !== isNowViolated) {
707
- node.nodeExistsConstraint = {
778
+ updatedNode.nodeExistsConstraint = {
708
779
  ...node.nodeExistsConstraint,
709
780
  violated: isNowViolated,
710
781
  };
@@ -714,7 +785,7 @@ class ModularChangeFamily {
714
785
  if (node.nodeExistsConstraintOnRevert !== undefined) {
715
786
  const isNowViolated = outputAttachState === fieldChangeHandler_js_1.NodeAttachState.Detached;
716
787
  if (node.nodeExistsConstraintOnRevert.violated !== isNowViolated) {
717
- node.nodeExistsConstraintOnRevert = {
788
+ updatedNode.nodeExistsConstraintOnRevert = {
718
789
  ...node.nodeExistsConstraintOnRevert,
719
790
  violated: isNowViolated,
720
791
  };
@@ -725,41 +796,82 @@ class ModularChangeFamily {
725
796
  this.updateConstraintsForFields(node.fieldChanges, inputAttachState, outputAttachState, constraintState, revertConstraintState, nodes);
726
797
  }
727
798
  }
728
- pruneFieldMap(changeset, nodeMap) {
799
+ pruneFieldMap(changeset, parentId, nodeMap, nodeToParent, aliases, roots, fieldsWithRootMoves, fieldsToRootChanges) {
729
800
  if (changeset === undefined) {
730
801
  return undefined;
731
802
  }
732
803
  const prunedChangeset = new Map();
733
804
  for (const [field, fieldChange] of changeset) {
734
805
  const handler = getChangeHandler(this.fieldKinds, fieldChange.fieldKind);
735
- const prunedFieldChangeset = handler.rebaser.prune(fieldChange.change, (nodeId) => this.pruneNodeChange(nodeId, nodeMap));
736
- if (!handler.isEmpty(prunedFieldChangeset)) {
806
+ const prunedFieldChangeset = handler.rebaser.prune(fieldChange.change, (nodeId) => this.pruneNodeChange(nodeId, nodeMap, nodeToParent, aliases, roots, fieldsWithRootMoves, fieldsToRootChanges));
807
+ const fieldId = { nodeId: parentId, field };
808
+ const fieldIdKey = fieldIdKeyFromFieldId(fieldId);
809
+ const rootsWithChanges = fieldsToRootChanges.get(fieldIdKey) ?? [];
810
+ let hasRootWithNodeChange = false;
811
+ for (const rootId of rootsWithChanges) {
812
+ const nodeId = (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(roots.nodeChanges, rootId) ?? (0, internal_1.fail)("No root change found");
813
+ const isRootChangeEmpty = this.pruneNodeChange(nodeId, nodeMap, nodeToParent, aliases, roots, fieldsWithRootMoves, fieldsToRootChanges) === undefined;
814
+ if (isRootChangeEmpty) {
815
+ roots.nodeChanges.delete([rootId.revision, rootId.localId]);
816
+ tryRemoveDetachLocation(roots, rootId, 1);
817
+ }
818
+ else {
819
+ hasRootWithNodeChange = true;
820
+ }
821
+ }
822
+ const hasRootChanges = hasRootWithNodeChange || fieldsWithRootMoves.get(fieldIdKey) === true;
823
+ if (!handler.isEmpty(prunedFieldChangeset) || hasRootChanges) {
737
824
  prunedChangeset.set(field, { ...fieldChange, change: (0, index_js_3.brand)(prunedFieldChangeset) });
738
825
  }
739
826
  }
740
827
  return prunedChangeset.size > 0 ? prunedChangeset : undefined;
741
828
  }
742
- pruneNodeChange(nodeId, nodeMap) {
743
- const changeset = nodeChangeFromId(nodeMap, nodeId);
829
+ pruneRoots(roots, nodeMap, nodeToParent, aliases, fieldsWithRootMoves, fieldsToRootChanges) {
830
+ const pruned = { ...roots, nodeChanges: (0, index_js_3.newTupleBTree)() };
831
+ for (const [rootIdKey, nodeId] of roots.nodeChanges.entries()) {
832
+ const rootId = { revision: rootIdKey[0], localId: rootIdKey[1] };
833
+ const hasDetachLocation = roots.detachLocations.getFirst(rootId, 1).value !== undefined;
834
+ // If the root has a detach location it should be pruned by recursion when pruning the field it was detached from.
835
+ const prunedId = hasDetachLocation
836
+ ? nodeId
837
+ : this.pruneNodeChange(nodeId, nodeMap, nodeToParent, aliases, roots, fieldsWithRootMoves, fieldsToRootChanges);
838
+ if (prunedId !== undefined) {
839
+ pruned.nodeChanges.set(rootIdKey, prunedId);
840
+ }
841
+ tryRemoveDetachLocation(pruned, rootId, 1);
842
+ }
843
+ return pruned;
844
+ }
845
+ pruneNodeChange(nodeId, nodes, nodeToParent, aliases, roots, fieldsWithRootMoves, fieldsToRootChanges) {
846
+ const changeset = nodeChangeFromId(nodes, aliases, nodeId);
744
847
  const prunedFields = changeset.fieldChanges === undefined
745
848
  ? undefined
746
- : this.pruneFieldMap(changeset.fieldChanges, nodeMap);
849
+ : this.pruneFieldMap(changeset.fieldChanges, nodeId, nodes, nodeToParent, aliases, roots, fieldsWithRootMoves, fieldsToRootChanges);
747
850
  const prunedChange = { ...changeset, fieldChanges: prunedFields };
748
851
  if (prunedChange.fieldChanges === undefined) {
749
852
  delete prunedChange.fieldChanges;
750
853
  }
751
854
  if (isEmptyNodeChangeset(prunedChange)) {
752
- nodeMap.delete([nodeId.revision, nodeId.localId]);
855
+ const nodeIdKey = [
856
+ nodeId.revision,
857
+ nodeId.localId,
858
+ ];
859
+ // TODO: Shouldn't we also delete all aliases associated with this node?
860
+ nodes.delete(nodeIdKey);
861
+ nodeToParent.delete(nodeIdKey);
753
862
  return undefined;
754
863
  }
755
864
  else {
756
- (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(nodeMap, nodeId, prunedChange);
865
+ (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(nodes, nodeId, prunedChange);
757
866
  return nodeId;
758
867
  }
759
868
  }
760
869
  getRevisions(change) {
870
+ if (change.revisions === undefined || change.revisions.length === 0) {
871
+ return new Set([undefined]);
872
+ }
761
873
  const aggregated = new Set();
762
- for (const revInfo of change.revisions ?? [{ revision: undefined }]) {
874
+ for (const revInfo of change.revisions) {
763
875
  aggregated.add(revInfo.revision);
764
876
  }
765
877
  return aggregated;
@@ -767,12 +879,13 @@ class ModularChangeFamily {
767
879
  changeRevision(change, replacer) {
768
880
  const updatedFields = this.replaceFieldMapRevisions(change.fieldChanges, replacer);
769
881
  const updatedNodes = replaceIdMapRevisions(change.nodeChanges, replacer, (nodeChangeset) => this.replaceNodeChangesetRevisions(nodeChangeset, replacer));
770
- const updatedNodeToParent = replaceIdMapRevisions(change.nodeToParent, replacer, (fieldId) => replaceFieldIdRevision(normalizeFieldId(fieldId, change.nodeAliases), replacer));
882
+ const updatedNodeToParent = replaceIdMapRevisions(change.nodeToParent, replacer, (location) => replaceNodeLocationRevision(normalizeNodeLocation(location, change.nodeAliases), replacer));
771
883
  const updated = {
772
884
  ...change,
773
885
  fieldChanges: updatedFields,
774
886
  nodeChanges: updatedNodes,
775
887
  nodeToParent: updatedNodeToParent,
888
+ rootNodes: replaceRootTableRevision(change.rootNodes, replacer, change.nodeAliases),
776
889
  // We've updated all references to old node IDs, so we no longer need an alias table.
777
890
  nodeAliases: (0, index_js_3.newTupleBTree)(),
778
891
  crossFieldKeys: replaceCrossFieldKeyTableRevisions(change.crossFieldKeys, replacer, change.nodeAliases),
@@ -805,7 +918,7 @@ class ModularChangeFamily {
805
918
  return updatedFields;
806
919
  }
807
920
  makeCrossFieldKeyTable(fields, nodes) {
808
- const keys = (0, modularChangeTypes_js_1.newCrossFieldKeyTable)();
921
+ const keys = (0, modularChangeTypes_js_1.newCrossFieldRangeTable)();
809
922
  this.populateCrossFieldKeyTableForFieldMap(keys, fields, undefined);
810
923
  nodes.forEachPair(([revision, localId], node) => {
811
924
  if (node.fieldChanges !== undefined) {
@@ -832,42 +945,6 @@ class ModularChangeFamily {
832
945
  const emptyChange = getChangeHandler(this.fieldKinds, fieldKind).createEmpty();
833
946
  return { fieldKind, change: (0, index_js_3.brand)(emptyChange) };
834
947
  }
835
- validateChangeset(change) {
836
- let numNodes = this.validateFieldChanges(change, change.fieldChanges, undefined);
837
- for (const [[revision, localId], node] of change.nodeChanges.entries()) {
838
- if (node.fieldChanges === undefined) {
839
- continue;
840
- }
841
- const nodeId = { revision, localId };
842
- const numChildren = this.validateFieldChanges(change, node.fieldChanges, nodeId);
843
- numNodes += numChildren;
844
- }
845
- (0, internal_1.assert)(numNodes === change.nodeChanges.size, 0xa4d /* Node table contains unparented nodes */);
846
- }
847
- /**
848
- * Asserts that each child and cross field key in each field has a correct entry in
849
- * `nodeToParent` or `crossFieldKeyTable`.
850
- * @returns the number of children found.
851
- */
852
- validateFieldChanges(change, fieldChanges, nodeParent) {
853
- let numChildren = 0;
854
- for (const [field, fieldChange] of fieldChanges.entries()) {
855
- const fieldId = { nodeId: nodeParent, field };
856
- const handler = getChangeHandler(this.fieldKinds, fieldChange.fieldKind);
857
- for (const [child, _index] of handler.getNestedChanges(fieldChange.change)) {
858
- const parentFieldId = getParentFieldId(change, child);
859
- (0, internal_1.assert)(areEqualFieldIds(parentFieldId, fieldId), 0xa4e /* Inconsistent node parentage */);
860
- numChildren += 1;
861
- }
862
- for (const keyRange of handler.getCrossFieldKeys(fieldChange.change)) {
863
- const fields = getFieldsForCrossFieldKey(change, keyRange.key, keyRange.count);
864
- (0, internal_1.assert)(fields.length === 1 &&
865
- fields[0] !== undefined &&
866
- areEqualFieldIds(fields[0], fieldId), 0xa4f /* Inconsistent cross field keys */);
867
- }
868
- }
869
- return numChildren;
870
- }
871
948
  getEffectiveChange(change) {
872
949
  if (hasConflicts(change)) {
873
950
  return this.muteChange(change);
@@ -880,7 +957,8 @@ class ModularChangeFamily {
880
957
  muteChange(change) {
881
958
  const muted = {
882
959
  ...change,
883
- crossFieldKeys: (0, modularChangeTypes_js_1.newCrossFieldKeyTable)(),
960
+ rootNodes: muteRootChanges(change.rootNodes),
961
+ crossFieldKeys: (0, modularChangeTypes_js_1.newCrossFieldRangeTable)(),
884
962
  fieldChanges: this.muteFieldChanges(change.fieldChanges),
885
963
  nodeChanges: (0, index_js_3.brand)(change.nodeChanges.mapValues((v) => this.muteNodeChange(v))),
886
964
  };
@@ -909,7 +987,7 @@ class ModularChangeFamily {
909
987
  exports.ModularChangeFamily = ModularChangeFamily;
910
988
  ModularChangeFamily.emptyChange = makeModularChangeset();
911
989
  function replaceCrossFieldKeyTableRevisions(table, replacer, nodeAliases) {
912
- const updated = (0, modularChangeTypes_js_1.newCrossFieldKeyTable)();
990
+ const updated = (0, modularChangeTypes_js_1.newCrossFieldRangeTable)();
913
991
  for (const entry of table.entries()) {
914
992
  const key = entry.start;
915
993
  const updatedKey = replacer.getUpdatedAtomId(key);
@@ -968,6 +1046,19 @@ function composeBuildsDestroysAndRefreshers(change1, change2) {
968
1046
  }
969
1047
  }
970
1048
  }
1049
+ // It's possible to have a build and a refresher for the same root because an attach operation need not be performed in the same changeset as the corresponding build.
1050
+ if (change1.builds !== undefined && change2.refreshers !== undefined) {
1051
+ for (const [key, chunk] of change2.refreshers.entries()) {
1052
+ (0, internal_1.assert)(chunk.topLevelLength === 1, "Expected refresher chunk to have length 1");
1053
+ const match = change1.builds.getPairOrNextLower(key);
1054
+ if (match !== undefined) {
1055
+ const [buildKey, buildChunk] = match;
1056
+ if (buildKey[0] === key[0] && buildKey[1] + buildChunk.topLevelLength > key[1]) {
1057
+ allRefreshers.delete(key);
1058
+ }
1059
+ }
1060
+ }
1061
+ }
971
1062
  return { allBuilds, allDestroys, allRefreshers };
972
1063
  }
973
1064
  function invertBuilds(builds) {
@@ -992,19 +1083,53 @@ function invertBuilds(builds) {
992
1083
  * @param fieldKinds - The field kinds to delegate to.
993
1084
  */
994
1085
  function* relevantRemovedRoots(change, fieldKinds) {
995
- yield* relevantRemovedRootsFromFields(change.fieldChanges, change.nodeChanges, fieldKinds);
1086
+ const rootIds = (0, index_js_2.newChangeAtomIdRangeMap)();
1087
+ addAttachesToSet(change, rootIds);
1088
+ addRenamesToSet(change, rootIds);
1089
+ for (const [[revision, localId]] of change.rootNodes.nodeChanges.entries()) {
1090
+ rootIds.set({ revision, localId }, 1, true);
1091
+ }
1092
+ for (const entry of rootIds.entries()) {
1093
+ for (let offset = 0; offset < entry.length; offset++) {
1094
+ const detachId = (0, index_js_2.offsetChangeAtomId)(entry.start, offset);
1095
+ yield (0, index_js_2.makeDetachedNodeId)(detachId.revision, detachId.localId);
1096
+ }
1097
+ }
996
1098
  }
997
1099
  exports.relevantRemovedRoots = relevantRemovedRoots;
998
- function* relevantRemovedRootsFromFields(change, nodeChanges, fieldKinds) {
999
- for (const [_, fieldChange] of change) {
1000
- const handler = getChangeHandler(fieldKinds, fieldChange.fieldKind);
1001
- const delegate = function* (node) {
1002
- const nodeChangeset = nodeChangeFromId(nodeChanges, node);
1003
- if (nodeChangeset.fieldChanges !== undefined) {
1004
- yield* relevantRemovedRootsFromFields(nodeChangeset.fieldChanges, nodeChanges, fieldKinds);
1100
+ function* getBuildIds(change) {
1101
+ if (change.builds !== undefined) {
1102
+ for (const [[revision, localId]] of change.builds.entries()) {
1103
+ yield (0, index_js_2.makeDetachedNodeId)(revision, localId);
1104
+ }
1105
+ }
1106
+ }
1107
+ exports.getBuildIds = getBuildIds;
1108
+ function addAttachesToSet(change, rootIds) {
1109
+ // This includes each attach which does not have a corresponding detach.
1110
+ for (const entry of change.crossFieldKeys.entries()) {
1111
+ if (entry.start.target !== crossFieldQueries_js_1.CrossFieldTarget.Destination) {
1112
+ continue;
1113
+ }
1114
+ for (const detachIdEntry of change.rootNodes.newToOldId.getAll2(entry.start, entry.length)) {
1115
+ const detachId = detachIdEntry.value ?? (0, index_js_2.offsetChangeAtomId)(entry.start, detachIdEntry.offset);
1116
+ for (const detachEntry of change.crossFieldKeys.getAll2({ ...detachId, target: crossFieldQueries_js_1.CrossFieldTarget.Source }, detachIdEntry.length)) {
1117
+ if (detachEntry.value === undefined) {
1118
+ rootIds.set((0, index_js_2.offsetChangeAtomId)(detachId, detachEntry.offset), detachEntry.length, true);
1119
+ }
1005
1120
  }
1006
- };
1007
- yield* handler.relevantRemovedRoots(fieldChange.change, delegate);
1121
+ }
1122
+ }
1123
+ }
1124
+ function addRenamesToSet(change, rootIds) {
1125
+ for (const renameEntry of change.rootNodes.oldToNewId.entries()) {
1126
+ for (const detachEntry of change.crossFieldKeys.getAll2({ ...renameEntry.start, target: crossFieldQueries_js_1.CrossFieldTarget.Source }, renameEntry.length)) {
1127
+ // We only want to include renames of nodes which are detached in the input context of the changeset.
1128
+ // So if there is a detach for the node, the rename is not relevant.
1129
+ if (detachEntry.value === undefined) {
1130
+ rootIds.set(renameEntry.start, renameEntry.length, true);
1131
+ }
1132
+ }
1008
1133
  }
1009
1134
  }
1010
1135
  /**
@@ -1050,13 +1175,14 @@ function updateRefreshers(change, getDetachedNode, removedRoots, requireRefreshe
1050
1175
  refreshers.set([root.major, (0, index_js_3.brand)(root.minor)], node);
1051
1176
  }
1052
1177
  }
1053
- const { fieldChanges, nodeChanges, nodeToParent, nodeAliases, crossFieldKeys, maxId, revisions, constraintViolationCount, constraintViolationCountOnRevert, builds, destroys, } = change;
1178
+ const { fieldChanges, nodeChanges, nodeToParent, nodeAliases, crossFieldKeys, maxId, revisions, constraintViolationCount, constraintViolationCountOnRevert, builds, destroys, rootNodes, } = change;
1054
1179
  return makeModularChangeset({
1055
1180
  fieldChanges,
1056
1181
  nodeChanges,
1057
1182
  nodeToParent,
1058
1183
  nodeAliases,
1059
1184
  crossFieldKeys,
1185
+ rootNodes,
1060
1186
  maxId: maxId,
1061
1187
  revisions,
1062
1188
  constraintViolationCount,
@@ -1076,11 +1202,24 @@ exports.updateRefreshers = updateRefreshers;
1076
1202
  function intoDelta(taggedChange, fieldKinds) {
1077
1203
  const change = taggedChange.change;
1078
1204
  const rootDelta = {};
1079
- const global = [];
1080
- const rename = [];
1081
1205
  if (!hasConflicts(change)) {
1082
1206
  // If there are no constraint violations, then tree changes apply.
1083
- const fieldDeltas = intoDeltaImpl(change.fieldChanges, change.nodeChanges, fieldKinds, global, rename);
1207
+ const fieldDeltas = intoDeltaImpl(change.fieldChanges, change.nodeChanges, change.nodeAliases, fieldKinds);
1208
+ const global = [];
1209
+ for (const [[major, minor], nodeId] of change.rootNodes.nodeChanges.entries()) {
1210
+ global.push({
1211
+ id: { major, minor },
1212
+ fields: deltaFromNodeChange(nodeChangeFromId(change.nodeChanges, change.nodeAliases, nodeId), change.nodeChanges, change.nodeAliases, fieldKinds),
1213
+ });
1214
+ }
1215
+ const rename = [];
1216
+ for (const { start: oldId, value: newId, length, } of change.rootNodes.oldToNewId.entries()) {
1217
+ rename.push({
1218
+ count: length,
1219
+ oldId: (0, index_js_2.makeDetachedNodeId)(oldId.revision, oldId.localId),
1220
+ newId: (0, index_js_2.makeDetachedNodeId)(newId.revision, newId.localId),
1221
+ });
1222
+ }
1084
1223
  if (fieldDeltas.size > 0) {
1085
1224
  rootDelta.fields = fieldDeltas;
1086
1225
  }
@@ -1127,24 +1266,22 @@ function copyDetachedNodes(detachedNodes) {
1127
1266
  /**
1128
1267
  * @param change - The change to convert into a delta.
1129
1268
  */
1130
- function intoDeltaImpl(change, nodeChanges, fieldKinds, global, rename) {
1269
+ function intoDeltaImpl(change, nodeChanges, nodeAliases, fieldKinds) {
1131
1270
  const delta = new Map();
1132
1271
  for (const [field, fieldChange] of change) {
1133
- const { local: fieldChanges, global: fieldGlobal, rename: fieldRename, } = getChangeHandler(fieldKinds, fieldChange.fieldKind).intoDelta(fieldChange.change, (childChange) => {
1134
- const nodeChange = nodeChangeFromId(nodeChanges, childChange);
1135
- return deltaFromNodeChange(nodeChange, nodeChanges, fieldKinds, global, rename);
1272
+ const fieldDelta = getChangeHandler(fieldKinds, fieldChange.fieldKind).intoDelta(fieldChange.change, (childChange) => {
1273
+ const nodeChange = nodeChangeFromId(nodeChanges, nodeAliases, childChange);
1274
+ return deltaFromNodeChange(nodeChange, nodeChanges, nodeAliases, fieldKinds);
1136
1275
  });
1137
- if (fieldChanges !== undefined && fieldChanges.length > 0) {
1138
- delta.set(field, fieldChanges);
1276
+ if (fieldDelta !== undefined && fieldDelta.length > 0) {
1277
+ delta.set(field, fieldDelta);
1139
1278
  }
1140
- fieldGlobal?.forEach((c) => global.push(c));
1141
- fieldRename?.forEach((r) => rename.push(r));
1142
1279
  }
1143
1280
  return delta;
1144
1281
  }
1145
- function deltaFromNodeChange(change, nodeChanges, fieldKinds, global, rename) {
1282
+ function deltaFromNodeChange(change, nodeChanges, nodeAliases, fieldKinds) {
1146
1283
  if (change.fieldChanges !== undefined) {
1147
- return intoDeltaImpl(change.fieldChanges, nodeChanges, fieldKinds, global, rename);
1284
+ return intoDeltaImpl(change.fieldChanges, nodeChanges, nodeAliases, fieldKinds);
1148
1285
  }
1149
1286
  // TODO: update the API to allow undefined to be returned here
1150
1287
  return new Map();
@@ -1194,30 +1331,22 @@ function getChangeHandler(fieldKinds, kind) {
1194
1331
  return getFieldKind(fieldKinds, kind).changeHandler;
1195
1332
  }
1196
1333
  exports.getChangeHandler = getChangeHandler;
1197
- function newComposeTable(baseChange, newChange, composedNodeToParent) {
1334
+ function newComposeTable(baseChange, newChange, composedRootNodes, movedCrossFieldKeys, removedCrossFieldKeys, pendingCompositions) {
1198
1335
  return {
1199
- ...newCrossFieldTable(),
1336
+ rebaseVersion: Math.max(baseChange.rebaseVersion, newChange.rebaseVersion),
1337
+ entries: newDetachedEntryMap(),
1200
1338
  baseChange,
1201
1339
  newChange,
1202
1340
  fieldToContext: new Map(),
1203
1341
  newFieldToBaseField: new Map(),
1204
1342
  newToBaseNodeId: (0, index_js_3.newTupleBTree)(),
1205
1343
  composedNodes: new Set(),
1206
- composedNodeToParent,
1207
- pendingCompositions: {
1208
- nodeIdsToCompose: [],
1209
- affectedBaseFields: (0, index_js_3.newTupleBTree)(),
1210
- affectedNewFields: (0, index_js_3.newTupleBTree)(),
1211
- },
1212
- };
1213
- }
1214
- function newCrossFieldTable() {
1215
- return {
1216
- srcTable: (0, index_js_2.newChangeAtomIdRangeMap)(),
1217
- dstTable: (0, index_js_2.newChangeAtomIdRangeMap)(),
1218
- srcDependents: (0, index_js_2.newChangeAtomIdRangeMap)(),
1219
- dstDependents: (0, index_js_2.newChangeAtomIdRangeMap)(),
1220
- invalidatedFields: new Set(),
1344
+ movedNodeToParent: (0, index_js_3.newTupleBTree)(),
1345
+ composedRootNodes,
1346
+ movedCrossFieldKeys,
1347
+ removedCrossFieldKeys,
1348
+ renamesToDelete: (0, index_js_2.newChangeAtomIdRangeMap)(),
1349
+ pendingCompositions,
1221
1350
  };
1222
1351
  }
1223
1352
  function newConstraintState(violationCount) {
@@ -1225,175 +1354,381 @@ function newConstraintState(violationCount) {
1225
1354
  violationCount,
1226
1355
  };
1227
1356
  }
1228
- class CrossFieldManagerI {
1229
- constructor(crossFieldTable, currentFieldKey, allowInval = true) {
1230
- this.crossFieldTable = crossFieldTable;
1231
- this.currentFieldKey = currentFieldKey;
1232
- this.allowInval = allowInval;
1357
+ class InvertNodeManagerI {
1358
+ constructor(table, fieldId) {
1359
+ this.table = table;
1360
+ this.fieldId = fieldId;
1233
1361
  }
1234
- set(target, revision, id, count, newValue, invalidateDependents) {
1235
- if (invalidateDependents && this.allowInval) {
1236
- const lastChangedId = id + count - 1;
1237
- let firstId = id;
1238
- while (firstId <= lastChangedId) {
1239
- const dependentEntry = (0, crossFieldQueries_js_1.getFirstFromCrossFieldMap)(this.getDependents(target), revision, firstId, lastChangedId - firstId + 1);
1240
- if (dependentEntry.value !== undefined) {
1241
- this.crossFieldTable.invalidatedFields.add(dependentEntry.value);
1362
+ invertDetach(detachId, count, nodeChange, newAttachId) {
1363
+ if (nodeChange !== undefined) {
1364
+ (0, internal_1.assert)(count === 1, "A node change should only affect one node");
1365
+ const attachEntry = firstAttachIdFromDetachId(this.table.change.rootNodes, detachId, count);
1366
+ const attachFieldEntry = this.table.change.crossFieldKeys.getFirst({ target: crossFieldQueries_js_1.CrossFieldTarget.Destination, ...attachEntry.value }, count);
1367
+ if (attachFieldEntry.value === undefined) {
1368
+ assignRootChange(this.table.invertedRoots, this.table.invertedNodeToParent, attachEntry.value, nodeChange, this.fieldId, this.table.change.rebaseVersion);
1369
+ }
1370
+ else {
1371
+ (0, crossFieldQueries_js_1.setInCrossFieldMap)(this.table.entries, attachEntry.value, count, nodeChange);
1372
+ this.table.invalidatedFields.add(fieldChangeFromId(this.table.change, attachFieldEntry.value));
1373
+ }
1374
+ }
1375
+ if (!(0, index_js_2.areEqualChangeAtomIds)(detachId, newAttachId)) {
1376
+ for (const entry of doesChangeAttachNodes(this.table.change.crossFieldKeys, detachId, count)) {
1377
+ if (!entry.value) {
1378
+ this.table.attachToDetachId.set(newAttachId, count, detachId);
1379
+ this.table.invertedRoots.detachLocations.set(detachId, count, this.fieldId);
1242
1380
  }
1243
- firstId = (0, index_js_3.brand)(firstId + dependentEntry.length);
1244
1381
  }
1245
1382
  }
1246
- (0, crossFieldQueries_js_1.setInCrossFieldMap)(this.getMap(target), revision, id, count, newValue);
1247
1383
  }
1248
- get(target, revision, id, count, addDependency) {
1249
- if (addDependency) {
1250
- // We assume that if there is already an entry for this ID it is because
1251
- // a field handler has called compose on the same node multiple times.
1252
- // In this case we only want to update the latest version, so we overwrite the dependency.
1253
- (0, crossFieldQueries_js_1.setInCrossFieldMap)(this.getDependents(target), revision, id, count, this.currentFieldKey);
1384
+ invertAttach(attachId, count) {
1385
+ let countToProcess = count;
1386
+ const detachIdEntry = firstDetachIdFromAttachId(this.table.change.rootNodes, attachId, countToProcess);
1387
+ countToProcess = detachIdEntry.length;
1388
+ const detachEntry = getFirstFieldForCrossFieldKey(this.table.change, { target: crossFieldQueries_js_1.CrossFieldTarget.Source, ...detachIdEntry.value }, countToProcess);
1389
+ countToProcess = detachEntry.length;
1390
+ let result;
1391
+ if (detachEntry.value === undefined) {
1392
+ // This node is detached in the input context of the original change.
1393
+ const nodeIdEntry = (0, changeAtomIdBTree_js_1.rangeQueryChangeAtomIdMap)(this.table.change.rootNodes.nodeChanges, detachIdEntry.value, countToProcess);
1394
+ countToProcess = nodeIdEntry.length;
1395
+ result = {
1396
+ value: { nodeChange: nodeIdEntry.value, detachId: detachIdEntry.value },
1397
+ length: countToProcess,
1398
+ };
1254
1399
  }
1255
- return (0, crossFieldQueries_js_1.getFirstFromCrossFieldMap)(this.getMap(target), revision, id, count);
1256
- }
1257
- getMap(target) {
1258
- return target === crossFieldQueries_js_1.CrossFieldTarget.Source
1259
- ? this.crossFieldTable.srcTable
1260
- : this.crossFieldTable.dstTable;
1261
- }
1262
- getDependents(target) {
1263
- return target === crossFieldQueries_js_1.CrossFieldTarget.Source
1264
- ? this.crossFieldTable.srcDependents
1265
- : this.crossFieldTable.dstDependents;
1266
- }
1267
- }
1268
- class InvertManager extends CrossFieldManagerI {
1269
- constructor(table, field, fieldId, allowInval = true) {
1270
- super(table, field, allowInval);
1271
- this.fieldId = fieldId;
1272
- }
1273
- onMoveIn(id) {
1274
- (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(this.table.invertedNodeToParent, id, this.fieldId);
1275
- }
1276
- moveKey(target, revision, id, count) {
1277
- (0, internal_1.assert)(false, 0x9c5 /* Keys should not be moved manually during invert */);
1278
- }
1279
- get table() {
1280
- return this.crossFieldTable;
1400
+ else {
1401
+ const moveEntry = this.table.entries.getFirst(attachId, countToProcess);
1402
+ result = { ...moveEntry, value: { nodeChange: moveEntry.value } };
1403
+ }
1404
+ if (result.value?.nodeChange !== undefined) {
1405
+ (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(this.table.invertedNodeToParent, result.value.nodeChange, {
1406
+ field: this.fieldId,
1407
+ });
1408
+ }
1409
+ return result;
1281
1410
  }
1282
1411
  }
1283
- class RebaseManager extends CrossFieldManagerI {
1284
- constructor(table, currentField, fieldId, allowInval = true) {
1285
- super(table, currentField, allowInval);
1412
+ class RebaseNodeManagerI {
1413
+ constructor(table, fieldId, allowInval = true) {
1414
+ this.table = table;
1286
1415
  this.fieldId = fieldId;
1416
+ this.allowInval = allowInval;
1287
1417
  }
1288
- set(target, revision, id, count, newValue, invalidateDependents) {
1289
- if (invalidateDependents && this.allowInval) {
1290
- const newFieldIds = getFieldsForCrossFieldKey(this.table.newChange, {
1291
- target,
1292
- revision,
1293
- localId: id,
1294
- }, count);
1295
- (0, internal_1.assert)(newFieldIds.length === 0, 0x9c6 /* TODO: Modifying a cross-field key from the new changeset is currently unsupported */);
1296
- const baseFieldIds = getFieldsForCrossFieldKey(this.table.baseChange, {
1297
- target,
1298
- revision,
1299
- localId: id,
1300
- }, count);
1301
- (0, internal_1.assert)(baseFieldIds.length > 0, 0x9c7 /* Cross field key not registered in base or new change */);
1302
- for (const baseFieldId of baseFieldIds) {
1303
- this.table.affectedBaseFields.set([baseFieldId.nodeId?.revision, baseFieldId.nodeId?.localId, baseFieldId.field], true);
1418
+ getNewChangesForBaseAttach(baseAttachId, count) {
1419
+ let countToProcess = count;
1420
+ const detachEntry = firstDetachIdFromAttachId(this.table.baseChange.rootNodes, baseAttachId, countToProcess);
1421
+ countToProcess = detachEntry.length;
1422
+ const nodeEntry = (0, changeAtomIdBTree_js_1.rangeQueryChangeAtomIdMap)(this.table.newChange.rootNodes.nodeChanges, detachEntry.value, countToProcess);
1423
+ countToProcess = nodeEntry.length;
1424
+ const newNodeId = nodeEntry.value;
1425
+ const newRenameEntry = this.table.newChange.rootNodes.oldToNewId.getFirst(detachEntry.value, countToProcess);
1426
+ countToProcess = newRenameEntry.length;
1427
+ let result;
1428
+ // eslint-disable-next-line unicorn/prefer-ternary
1429
+ if (newNodeId !== undefined || newRenameEntry.value !== undefined) {
1430
+ result = {
1431
+ ...newRenameEntry,
1432
+ value: { detachId: newRenameEntry.value, nodeChange: newNodeId },
1433
+ };
1434
+ }
1435
+ else {
1436
+ // This handles the case where the base changeset has moved these nodes,
1437
+ // meaning they were attached in the input context of the base changeset.
1438
+ result = this.table.entries.getFirst(baseAttachId, countToProcess);
1439
+ }
1440
+ // TODO: Consider moving these two checks into a separate method so that this function has no side effects.
1441
+ if (result.value?.detachId !== undefined) {
1442
+ this.table.rebasedDetachLocations.set(result.value.detachId, result.length, this.fieldId);
1443
+ }
1444
+ if (result.value?.nodeChange !== undefined) {
1445
+ (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(this.table.rebasedNodeToParent, result.value.nodeChange, {
1446
+ field: this.fieldId,
1447
+ });
1448
+ }
1449
+ return result;
1450
+ }
1451
+ rebaseOverDetach(baseDetachId, count, newDetachId, nodeChange, cellRename) {
1452
+ let countToProcess = count;
1453
+ const attachIdEntry = firstAttachIdFromDetachId(this.table.baseRoots, baseDetachId, countToProcess);
1454
+ const baseAttachId = attachIdEntry.value;
1455
+ countToProcess = attachIdEntry.length;
1456
+ const attachFieldEntry = getFirstFieldForCrossFieldKey(this.table.baseChange, { ...baseAttachId, target: crossFieldQueries_js_1.CrossFieldTarget.Destination }, countToProcess);
1457
+ countToProcess = attachFieldEntry.length;
1458
+ const detachedMoveEntry = this.table.baseChange.rootNodes.outputDetachLocations.getFirst(baseDetachId, countToProcess);
1459
+ countToProcess = detachedMoveEntry.length;
1460
+ const destinationField = attachFieldEntry.value ?? detachedMoveEntry.value;
1461
+ if (destinationField !== undefined) {
1462
+ // The base detach is part of a move (or move of detach location) in the base changeset.
1463
+ (0, crossFieldQueries_js_1.setInCrossFieldMap)(this.table.entries, baseAttachId, countToProcess, {
1464
+ nodeChange,
1465
+ detachId: newDetachId,
1466
+ cellRename,
1467
+ });
1468
+ if (nodeChange !== undefined || newDetachId !== undefined) {
1469
+ this.invalidateBaseFields([destinationField]);
1470
+ }
1471
+ }
1472
+ if (attachFieldEntry.value === undefined) {
1473
+ // These nodes are detached in the output context of the base changeset.
1474
+ if (nodeChange !== undefined) {
1475
+ assignRootChange(this.table.rebasedRootNodes, this.table.rebasedNodeToParent, baseAttachId, nodeChange, this.fieldId, this.table.rebaseVersion);
1476
+ }
1477
+ if (newDetachId !== undefined) {
1478
+ addNodeRename(this.table.rebasedRootNodes, baseAttachId, newDetachId, countToProcess, this.fieldId);
1479
+ }
1480
+ }
1481
+ if (newDetachId !== undefined) {
1482
+ this.table.movedDetaches.set(newDetachId, countToProcess, true);
1483
+ }
1484
+ if (countToProcess < count) {
1485
+ const remainingCount = count - countToProcess;
1486
+ const nextDetachId = newDetachId === undefined
1487
+ ? undefined
1488
+ : (0, index_js_2.offsetChangeAtomId)(newDetachId, countToProcess);
1489
+ this.rebaseOverDetach((0, index_js_2.offsetChangeAtomId)(baseDetachId, countToProcess), remainingCount, nextDetachId, nodeChange);
1490
+ }
1491
+ }
1492
+ addDetach(id, count) {
1493
+ this.table.rebasedDetachLocations.set(id, count, this.fieldId);
1494
+ }
1495
+ removeDetach(id, count) {
1496
+ this.table.movedDetaches.set(id, count, true);
1497
+ }
1498
+ doesBaseAttachNodes(id, count) {
1499
+ let countToProcess = count;
1500
+ const attachEntry = getFirstAttachField(this.table.baseChange.crossFieldKeys, id, countToProcess);
1501
+ countToProcess = attachEntry.length;
1502
+ return { start: id, value: attachEntry.value !== undefined, length: countToProcess };
1503
+ }
1504
+ getBaseRename(id, count) {
1505
+ return this.table.baseChange.rootNodes.oldToNewId.getFirst(id, count);
1506
+ }
1507
+ getNewRenameForBaseRename(baseRenameTo, count) {
1508
+ let countToProcess = count;
1509
+ const inputEntry = firstDetachIdFromAttachId(this.table.baseChange.rootNodes, baseRenameTo, countToProcess);
1510
+ const attachEntry = getFirstAttachField(this.table.baseChange.crossFieldKeys, baseRenameTo, countToProcess);
1511
+ countToProcess = attachEntry.length;
1512
+ if (attachEntry.value !== undefined) {
1513
+ // These nodes are attached in the output context of the base changeset.
1514
+ return { value: undefined, length: countToProcess };
1515
+ }
1516
+ countToProcess = inputEntry.length;
1517
+ const inputId = inputEntry.value;
1518
+ const moveEntry = this.table.entries.getFirst(inputId, countToProcess);
1519
+ countToProcess = moveEntry.length;
1520
+ if (moveEntry.value !== undefined) {
1521
+ return { ...moveEntry, value: moveEntry.value.cellRename ?? moveEntry.value.detachId };
1522
+ }
1523
+ return this.table.newChange.rootNodes.oldToNewId.getFirst(inputId, countToProcess);
1524
+ }
1525
+ invalidateBaseFields(fields) {
1526
+ if (this.allowInval) {
1527
+ for (const fieldId of fields) {
1528
+ this.table.affectedBaseFields.set(fieldIdKeyFromFieldId(fieldId), true);
1304
1529
  }
1305
1530
  }
1306
- super.set(target, revision, id, count, newValue, invalidateDependents);
1307
- }
1308
- onMoveIn(id) {
1309
- (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(this.table.rebasedNodeToParent, id, this.fieldId);
1310
- }
1311
- moveKey(target, revision, id, count) {
1312
- this.table.rebasedCrossFieldKeys.set({ target, revision, localId: id }, count, this.fieldId);
1313
1531
  }
1314
- get table() {
1315
- return this.crossFieldTable;
1532
+ }
1533
+ function assignRootChange(table, nodeToParent, detachId, nodeId, detachLocation, rebaseVersion) {
1534
+ (0, internal_1.assert)(rebaseVersion >= 2 || detachLocation !== undefined, "All root changes need a detach location to support compatibility with older client versions");
1535
+ (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(table.nodeChanges, detachId, nodeId);
1536
+ if (nodeToParent !== undefined) {
1537
+ (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(nodeToParent, nodeId, { root: detachId });
1316
1538
  }
1539
+ table.detachLocations.set(detachId, 1, detachLocation);
1317
1540
  }
1318
- // TODO: Deduplicate this with RebaseTable
1319
- class ComposeManager extends CrossFieldManagerI {
1320
- constructor(table, currentField, fieldId, allowInval = true) {
1321
- super(table, currentField, allowInval);
1541
+ class ComposeNodeManagerI {
1542
+ constructor(table, fieldId, allowInval = true) {
1543
+ this.table = table;
1322
1544
  this.fieldId = fieldId;
1545
+ this.allowInval = allowInval;
1323
1546
  }
1324
- set(target, revision, id, count, newValue, invalidateDependents) {
1325
- if (invalidateDependents && this.allowInval) {
1326
- const newFieldIds = getFieldsForCrossFieldKey(this.table.newChange, {
1327
- target,
1328
- revision,
1329
- localId: id,
1330
- }, count);
1331
- if (newFieldIds.length > 0) {
1332
- for (const newFieldId of newFieldIds) {
1333
- this.table.pendingCompositions.affectedNewFields.set([newFieldId.nodeId?.revision, newFieldId.nodeId?.localId, newFieldId.field], true);
1334
- }
1547
+ getNewChangesForBaseDetach(baseDetachId, count) {
1548
+ let countToProcess = count;
1549
+ const baseAttachEntry = getFirstFieldForCrossFieldKey(this.table.baseChange, { target: crossFieldQueries_js_1.CrossFieldTarget.Destination, ...baseDetachId }, countToProcess);
1550
+ countToProcess = baseAttachEntry.length;
1551
+ let result;
1552
+ if (baseAttachEntry.value === undefined) {
1553
+ // The detached nodes are still detached in the new change's input context.
1554
+ const rootEntry = (0, changeAtomIdBTree_js_1.rangeQueryChangeAtomIdMap)(this.table.newChange.rootNodes.nodeChanges, baseDetachId, countToProcess);
1555
+ countToProcess = rootEntry.length;
1556
+ const newRenameEntry = this.table.newChange.rootNodes.oldToNewId.getFirst(baseDetachId, countToProcess);
1557
+ countToProcess = newRenameEntry.length;
1558
+ result = {
1559
+ value: { nodeChange: rootEntry.value, detachId: newRenameEntry.value },
1560
+ length: countToProcess,
1561
+ };
1562
+ }
1563
+ else {
1564
+ // The base detach was part of a move.
1565
+ // We check if we've previously seen a node change at the move destination.
1566
+ const entry = this.table.entries.getFirst(baseDetachId, countToProcess);
1567
+ result = { value: entry.value, length: entry.length };
1568
+ }
1569
+ // TODO: Consider moving this to a separate method so that this method can be side-effect free.
1570
+ if (result.value?.nodeChange !== undefined) {
1571
+ (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(this.table.movedNodeToParent, result.value.nodeChange, {
1572
+ field: this.fieldId,
1573
+ });
1574
+ }
1575
+ return result;
1576
+ }
1577
+ composeAttachDetach(baseAttachId, newDetachId, count) {
1578
+ let countToProcess = count;
1579
+ const newAttachEntry = getFirstAttachField(this.table.newChange.crossFieldKeys, newDetachId, countToProcess);
1580
+ countToProcess = newAttachEntry.length;
1581
+ // Both changes can have the same ID if they came from inverse changesets.
1582
+ // If the new detach is part of a move,
1583
+ // then both input changesets contain the attach cross-field key for this ID.
1584
+ // The new attach may still exist in the composed changeset so we do not remove it here.
1585
+ // The new attach will typically cancel with a base detach,
1586
+ // in which case the cross-field key will be removed in `composeDetachAttach`.
1587
+ const hasNewAttachWithBaseAttachId = (0, index_js_2.areEqualChangeAtomIds)(baseAttachId, newDetachId) && newAttachEntry.value !== undefined;
1588
+ if (!hasNewAttachWithBaseAttachId) {
1589
+ this.table.removedCrossFieldKeys.set({ ...baseAttachId, target: crossFieldQueries_js_1.CrossFieldTarget.Destination }, countToProcess, true);
1590
+ }
1591
+ const baseDetachEntry = getFirstDetachField(this.table.baseChange.crossFieldKeys, baseAttachId, countToProcess);
1592
+ countToProcess = baseDetachEntry.length;
1593
+ const baseRootIdEntry = firstDetachIdFromAttachId(this.table.baseChange.rootNodes, baseAttachId, countToProcess);
1594
+ countToProcess = baseRootIdEntry.length;
1595
+ const baseDetachId = baseRootIdEntry.value;
1596
+ if (baseDetachEntry.value === undefined) {
1597
+ const baseDetachLocationEntry = this.table.baseChange.rootNodes.detachLocations.getFirst(baseDetachId, countToProcess);
1598
+ countToProcess = baseDetachLocationEntry.length;
1599
+ // These nodes were detached in the base change's input context,
1600
+ // so the net effect of the two changes is a rename.
1601
+ appendNodeRename(this.table.composedRootNodes, baseAttachId, newDetachId, baseDetachEntry.length, this.table.baseChange.rootNodes, baseDetachLocationEntry.value ?? this.fieldId);
1602
+ this.table.removedCrossFieldKeys.set({ ...newDetachId, target: crossFieldQueries_js_1.CrossFieldTarget.Source }, countToProcess, true);
1603
+ }
1604
+ else {
1605
+ // The base change moves these nodes.
1606
+ const prevEntry = this.table.entries.getFirst(baseAttachId, baseDetachEntry.length).value ?? {};
1607
+ this.table.entries.set(baseAttachId, baseDetachEntry.length, {
1608
+ ...prevEntry,
1609
+ detachId: newDetachId,
1610
+ });
1611
+ // The new detach will replace the base detach, so we remove the key for the base detach, unless they have the same ID.
1612
+ if (!(0, index_js_2.areEqualChangeAtomIds)(baseAttachId, newDetachId)) {
1613
+ this.table.removedCrossFieldKeys.set({ ...baseAttachId, target: crossFieldQueries_js_1.CrossFieldTarget.Source }, countToProcess, true);
1614
+ }
1615
+ this.table.movedCrossFieldKeys.set({ ...newDetachId, target: crossFieldQueries_js_1.CrossFieldTarget.Source }, countToProcess, baseDetachEntry.value);
1616
+ this.invalidateBaseFields([baseDetachEntry.value]);
1617
+ }
1618
+ if (newAttachEntry.value === undefined) {
1619
+ const newOutputDetachLocationEntry = this.table.newChange.rootNodes.outputDetachLocations.getFirst(newDetachId, countToProcess);
1620
+ countToProcess = newOutputDetachLocationEntry.length;
1621
+ this.table.composedRootNodes.outputDetachLocations.set(newDetachId, countToProcess, newOutputDetachLocationEntry.value ?? this.fieldId);
1622
+ }
1623
+ if (countToProcess < count) {
1624
+ const remainingCount = count - countToProcess;
1625
+ this.composeAttachDetach((0, index_js_2.offsetChangeAtomId)(baseAttachId, countToProcess), (0, index_js_2.offsetChangeAtomId)(newDetachId, countToProcess), remainingCount);
1626
+ }
1627
+ }
1628
+ sendNewChangesToBaseSourceLocation(baseAttachId, newChanges) {
1629
+ const { value: baseDetachId } = firstDetachIdFromAttachId(this.table.baseChange.rootNodes, baseAttachId, 1);
1630
+ const detachFields = getFieldsForCrossFieldKey(this.table.baseChange, {
1631
+ ...baseDetachId,
1632
+ target: crossFieldQueries_js_1.CrossFieldTarget.Source,
1633
+ }, 1);
1634
+ if (detachFields.length > 0) {
1635
+ // The base attach is part of a move in the base changeset.
1636
+ const prevEntry = this.table.entries.getFirst(baseDetachId, 1).value ?? {};
1637
+ this.table.entries.set(baseDetachId, 1, { ...prevEntry, nodeChange: newChanges });
1638
+ if (newChanges !== undefined) {
1639
+ this.invalidateBaseFields(detachFields);
1640
+ }
1641
+ }
1642
+ else {
1643
+ const baseNodeId = (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(this.table.baseChange.rootNodes.nodeChanges, baseDetachId);
1644
+ if (baseNodeId === undefined) {
1645
+ assignRootChange(this.table.composedRootNodes, this.table.movedNodeToParent, baseDetachId, newChanges, this.fieldId, this.table.rebaseVersion);
1335
1646
  }
1336
1647
  else {
1337
- const baseFieldIds = getFieldsForCrossFieldKey(this.table.baseChange, {
1338
- target,
1339
- revision,
1340
- localId: id,
1341
- }, count);
1342
- (0, internal_1.assert)(baseFieldIds.length > 0, 0x9c8 /* Cross field key not registered in base or new change */);
1343
- for (const baseFieldId of baseFieldIds) {
1344
- this.table.pendingCompositions.affectedBaseFields.set([baseFieldId.nodeId?.revision, baseFieldId.nodeId?.localId, baseFieldId.field], true);
1345
- }
1648
+ addNodesToCompose(this.table, baseNodeId, newChanges);
1346
1649
  }
1347
1650
  }
1348
- super.set(target, revision, id, count, newValue, invalidateDependents);
1349
- }
1350
- onMoveIn(id) {
1351
- (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(this.table.composedNodeToParent, id, this.fieldId);
1352
1651
  }
1353
- moveKey(target, revision, id, count) {
1354
- throw new Error("Moving cross-field keys during compose is currently unsupported");
1652
+ areSameNodes(baseDetachId, newAttachId, count) {
1653
+ const renamedDetachEntry = firstAttachIdFromDetachId(this.table.composedRootNodes, baseDetachId, count);
1654
+ const isReattachOfSameNodes = (0, index_js_2.areEqualChangeAtomIds)(renamedDetachEntry.value, newAttachId);
1655
+ return { ...renamedDetachEntry, value: isReattachOfSameNodes };
1656
+ }
1657
+ composeDetachAttach(baseDetachId, newAttachId, count, composeToPin) {
1658
+ const areSameEntry = this.areSameNodes(baseDetachId, newAttachId, count);
1659
+ const countToProcess = areSameEntry.length;
1660
+ if (areSameEntry.value) {
1661
+ // These nodes have been moved back to their original location, so the composed changeset should not have any renames for them.
1662
+ // Note that deleting the rename from `this.table.composedRootNodes` would change the result of this method
1663
+ // if it were rerun due to the field being invalidated, so we instead record that the rename should be deleted later.
1664
+ this.table.renamesToDelete.set(baseDetachId, countToProcess, true);
1665
+ }
1666
+ if (composeToPin) {
1667
+ this.table.movedCrossFieldKeys.set({ target: crossFieldQueries_js_1.CrossFieldTarget.Source, ...newAttachId }, countToProcess, this.fieldId);
1668
+ if (!(0, index_js_2.areEqualChangeAtomIds)(baseDetachId, newAttachId)) {
1669
+ // The pin will have `newAttachId` as both its detach and attach ID.
1670
+ // So we remove `baseDetachId` unless that is equal to the pin's detach ID.
1671
+ this.table.removedCrossFieldKeys.set({ target: crossFieldQueries_js_1.CrossFieldTarget.Source, ...baseDetachId }, countToProcess, true);
1672
+ }
1673
+ // Note that while change2 should already have this key, change1 may have a rollback for the same ID in a different location.
1674
+ // In that case, change1's attach should be canceled out by a detach from change2.
1675
+ // Here we make sure that the composed change has the correct location (this field) for the attach ID.
1676
+ this.table.movedCrossFieldKeys.set({ target: crossFieldQueries_js_1.CrossFieldTarget.Destination, ...newAttachId }, countToProcess, this.fieldId);
1677
+ }
1678
+ else {
1679
+ this.table.removedCrossFieldKeys.set({ target: crossFieldQueries_js_1.CrossFieldTarget.Source, ...baseDetachId }, countToProcess, true);
1680
+ this.table.removedCrossFieldKeys.set({ target: crossFieldQueries_js_1.CrossFieldTarget.Destination, ...newAttachId }, countToProcess, true);
1681
+ }
1682
+ if (countToProcess < count) {
1683
+ this.composeAttachDetach((0, index_js_2.offsetChangeAtomId)(baseDetachId, countToProcess), (0, index_js_2.offsetChangeAtomId)(newAttachId, countToProcess), count - countToProcess);
1684
+ }
1355
1685
  }
1356
- get table() {
1357
- return this.crossFieldTable;
1686
+ invalidateBaseFields(fields) {
1687
+ if (this.allowInval) {
1688
+ for (const fieldId of fields) {
1689
+ this.table.pendingCompositions.affectedBaseFields.set(fieldIdKeyFromFieldId(fieldId), true);
1690
+ }
1691
+ }
1358
1692
  }
1359
1693
  }
1360
- function makeModularChangeset(props = {
1361
- maxId: -1,
1362
- }) {
1694
+ function makeModularChangeset(props) {
1695
+ const p = props ?? { maxId: -1 };
1363
1696
  const changeset = {
1364
- fieldChanges: props.fieldChanges ?? new Map(),
1365
- nodeChanges: props.nodeChanges ?? (0, index_js_3.newTupleBTree)(),
1366
- nodeToParent: props.nodeToParent ?? (0, index_js_3.newTupleBTree)(),
1367
- nodeAliases: props.nodeAliases ?? (0, index_js_3.newTupleBTree)(),
1368
- crossFieldKeys: props.crossFieldKeys ?? (0, modularChangeTypes_js_1.newCrossFieldKeyTable)(),
1697
+ rebaseVersion: p.rebaseVersion ?? 1,
1698
+ fieldChanges: p.fieldChanges ?? new Map(),
1699
+ nodeChanges: p.nodeChanges ?? (0, index_js_3.newTupleBTree)(),
1700
+ rootNodes: p.rootNodes ?? newRootTable(),
1701
+ nodeToParent: p.nodeToParent ?? (0, index_js_3.newTupleBTree)(),
1702
+ nodeAliases: p.nodeAliases ?? (0, index_js_3.newTupleBTree)(),
1703
+ crossFieldKeys: p.crossFieldKeys ?? (0, modularChangeTypes_js_1.newCrossFieldRangeTable)(),
1369
1704
  };
1370
- if (props.revisions !== undefined && props.revisions.length > 0) {
1371
- changeset.revisions = props.revisions;
1705
+ if (p.revisions !== undefined && p.revisions.length > 0) {
1706
+ changeset.revisions = p.revisions;
1372
1707
  }
1373
- if (props.maxId >= 0) {
1374
- changeset.maxId = (0, index_js_3.brand)(props.maxId);
1708
+ if (p.maxId >= 0) {
1709
+ changeset.maxId = (0, index_js_3.brand)(p.maxId);
1375
1710
  }
1376
- if (props.constraintViolationCount !== undefined && props.constraintViolationCount > 0) {
1377
- changeset.constraintViolationCount = props.constraintViolationCount;
1711
+ if (p.constraintViolationCount !== undefined && p.constraintViolationCount > 0) {
1712
+ changeset.constraintViolationCount = p.constraintViolationCount;
1378
1713
  }
1379
- if (props.constraintViolationCountOnRevert !== undefined &&
1380
- props.constraintViolationCountOnRevert > 0) {
1381
- changeset.constraintViolationCountOnRevert = props.constraintViolationCountOnRevert;
1714
+ if (p.constraintViolationCountOnRevert !== undefined &&
1715
+ p.constraintViolationCountOnRevert > 0) {
1716
+ changeset.constraintViolationCountOnRevert = p.constraintViolationCountOnRevert;
1382
1717
  }
1383
- if (props.noChangeConstraint !== undefined) {
1384
- changeset.noChangeConstraint = props.noChangeConstraint;
1718
+ if (p.noChangeConstraint !== undefined) {
1719
+ changeset.noChangeConstraint = p.noChangeConstraint;
1385
1720
  }
1386
- if (props.noChangeConstraintOnRevert !== undefined) {
1387
- changeset.noChangeConstraintOnRevert = props.noChangeConstraintOnRevert;
1721
+ if (p.noChangeConstraintOnRevert !== undefined) {
1722
+ changeset.noChangeConstraintOnRevert = p.noChangeConstraintOnRevert;
1388
1723
  }
1389
- if (props.builds !== undefined && props.builds.size > 0) {
1390
- changeset.builds = props.builds;
1724
+ if (p.builds !== undefined && p.builds.size > 0) {
1725
+ changeset.builds = p.builds;
1391
1726
  }
1392
- if (props.destroys !== undefined && props.destroys.size > 0) {
1393
- changeset.destroys = props.destroys;
1727
+ if (p.destroys !== undefined && p.destroys.size > 0) {
1728
+ changeset.destroys = p.destroys;
1394
1729
  }
1395
- if (props.refreshers !== undefined && props.refreshers.size > 0) {
1396
- changeset.refreshers = props.refreshers;
1730
+ if (p.refreshers !== undefined && p.refreshers.size > 0) {
1731
+ changeset.refreshers = p.refreshers;
1397
1732
  }
1398
1733
  return changeset;
1399
1734
  }
@@ -1405,6 +1740,9 @@ class ModularEditBuilder extends index_js_2.EditBuilder {
1405
1740
  this.idAllocator = (0, index_js_3.idAllocatorFromMaxId)();
1406
1741
  this.codecOptions = codecOptions;
1407
1742
  }
1743
+ isInTransaction() {
1744
+ return this.transactionDepth > 0;
1745
+ }
1408
1746
  enterTransaction() {
1409
1747
  this.transactionDepth += 1;
1410
1748
  if (this.transactionDepth === 1) {
@@ -1455,7 +1793,8 @@ class ModularEditBuilder extends index_js_2.EditBuilder {
1455
1793
  fieldChange: { fieldKind, change },
1456
1794
  nodeChanges: (0, index_js_3.newTupleBTree)(),
1457
1795
  nodeToParent: (0, index_js_3.newTupleBTree)(),
1458
- crossFieldKeys: (0, modularChangeTypes_js_1.newCrossFieldKeyTable)(),
1796
+ crossFieldKeys: (0, modularChangeTypes_js_1.newCrossFieldRangeTable)(),
1797
+ rootNodes: newRootTable(),
1459
1798
  idAllocator: this.idAllocator,
1460
1799
  localCrossFieldKeys,
1461
1800
  revision,
@@ -1474,6 +1813,7 @@ class ModularEditBuilder extends index_js_2.EditBuilder {
1474
1813
  ? makeModularChangeset({
1475
1814
  maxId: this.idAllocator.getMaxId(),
1476
1815
  builds: change.builds,
1816
+ rootNodes: renameTableFromRenameDescriptions(change.renames ?? []),
1477
1817
  revisions: [{ revision: change.revision }],
1478
1818
  })
1479
1819
  : buildModularChangesetFromField({
@@ -1484,7 +1824,8 @@ class ModularEditBuilder extends index_js_2.EditBuilder {
1484
1824
  },
1485
1825
  nodeChanges: (0, index_js_3.newTupleBTree)(),
1486
1826
  nodeToParent: (0, index_js_3.newTupleBTree)(),
1487
- crossFieldKeys: (0, modularChangeTypes_js_1.newCrossFieldKeyTable)(),
1827
+ crossFieldKeys: (0, modularChangeTypes_js_1.newCrossFieldRangeTable)(),
1828
+ rootNodes: newRootTable(),
1488
1829
  idAllocator: this.idAllocator,
1489
1830
  localCrossFieldKeys: getChangeHandler(this.fieldKinds, change.fieldKind).getCrossFieldKeys(change.change),
1490
1831
  revision: change.revision,
@@ -1513,7 +1854,8 @@ class ModularEditBuilder extends index_js_2.EditBuilder {
1513
1854
  nodeChange,
1514
1855
  nodeChanges: (0, index_js_3.newTupleBTree)(),
1515
1856
  nodeToParent: (0, index_js_3.newTupleBTree)(),
1516
- crossFieldKeys: (0, modularChangeTypes_js_1.newCrossFieldKeyTable)(),
1857
+ crossFieldKeys: (0, modularChangeTypes_js_1.newCrossFieldRangeTable)(),
1858
+ rootNodes: newRootTable(),
1517
1859
  idAllocator: this.idAllocator,
1518
1860
  revision,
1519
1861
  }), revision));
@@ -1527,7 +1869,8 @@ class ModularEditBuilder extends index_js_2.EditBuilder {
1527
1869
  nodeChange,
1528
1870
  nodeChanges: (0, index_js_3.newTupleBTree)(),
1529
1871
  nodeToParent: (0, index_js_3.newTupleBTree)(),
1530
- crossFieldKeys: (0, modularChangeTypes_js_1.newCrossFieldKeyTable)(),
1872
+ crossFieldKeys: (0, modularChangeTypes_js_1.newCrossFieldRangeTable)(),
1873
+ rootNodes: newRootTable(),
1531
1874
  idAllocator: this.idAllocator,
1532
1875
  revision,
1533
1876
  }), revision));
@@ -1555,16 +1898,19 @@ class ModularEditBuilder extends index_js_2.EditBuilder {
1555
1898
  }
1556
1899
  exports.ModularEditBuilder = ModularEditBuilder;
1557
1900
  function buildModularChangesetFromField(props) {
1558
- const { path, fieldChange, nodeChanges, nodeToParent, crossFieldKeys, idAllocator = (0, index_js_3.idAllocatorFromMaxId)(), localCrossFieldKeys = [], childId, revision, } = props;
1901
+ const { path, fieldChange, nodeChanges, nodeToParent, crossFieldKeys, rootNodes, idAllocator = (0, index_js_3.idAllocatorFromMaxId)(), localCrossFieldKeys = [], childId, revision, } = props;
1559
1902
  const fieldChanges = new Map([[path.field, fieldChange]]);
1560
1903
  if (path.parent === undefined) {
1904
+ const field = { nodeId: undefined, field: path.field };
1561
1905
  for (const { key, count } of localCrossFieldKeys) {
1562
- crossFieldKeys.set(key, count, { nodeId: undefined, field: path.field });
1906
+ crossFieldKeys.set(key, count, field);
1563
1907
  }
1564
1908
  if (childId !== undefined) {
1565
1909
  (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(nodeToParent, childId, {
1566
- nodeId: undefined,
1567
- field: path.field,
1910
+ field: {
1911
+ nodeId: undefined,
1912
+ field: path.field,
1913
+ },
1568
1914
  });
1569
1915
  }
1570
1916
  return makeModularChangeset({
@@ -1572,6 +1918,7 @@ function buildModularChangesetFromField(props) {
1572
1918
  nodeChanges,
1573
1919
  nodeToParent,
1574
1920
  crossFieldKeys,
1921
+ rootNodes,
1575
1922
  maxId: idAllocator.getMaxId(),
1576
1923
  revisions: [{ revision }],
1577
1924
  });
@@ -1580,13 +1927,13 @@ function buildModularChangesetFromField(props) {
1580
1927
  fieldChanges,
1581
1928
  };
1582
1929
  const parentId = { localId: (0, index_js_3.brand)(idAllocator.allocate()), revision };
1930
+ const fieldId = { nodeId: parentId, field: path.field };
1583
1931
  for (const { key, count } of localCrossFieldKeys) {
1584
1932
  crossFieldKeys.set(key, count, { nodeId: parentId, field: path.field });
1585
1933
  }
1586
1934
  if (childId !== undefined) {
1587
1935
  (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(nodeToParent, childId, {
1588
- nodeId: parentId,
1589
- field: path.field,
1936
+ field: fieldId,
1590
1937
  });
1591
1938
  }
1592
1939
  return buildModularChangesetFromNode({
@@ -1595,28 +1942,50 @@ function buildModularChangesetFromField(props) {
1595
1942
  nodeChanges,
1596
1943
  nodeToParent,
1597
1944
  crossFieldKeys,
1945
+ rootNodes,
1598
1946
  idAllocator,
1599
1947
  revision,
1600
1948
  nodeId: parentId,
1601
1949
  });
1602
1950
  }
1951
+ exports.buildModularChangesetFromField = buildModularChangesetFromField;
1603
1952
  function buildModularChangesetFromNode(props) {
1604
1953
  const { path, idAllocator, revision, nodeChanges, nodeChange, nodeId = { localId: (0, index_js_3.brand)(idAllocator.allocate()), revision }, } = props;
1605
1954
  (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(nodeChanges, nodeId, nodeChange);
1606
- const fieldChangeset = genericFieldKind_js_1.genericFieldKind.changeHandler.editor.buildChildChanges([
1607
- [path.parentIndex, nodeId],
1608
- ]);
1609
- const fieldChange = {
1610
- fieldKind: genericFieldKind_js_1.genericFieldKind.identifier,
1611
- change: fieldChangeset,
1612
- };
1613
- return buildModularChangesetFromField({
1614
- ...props,
1615
- path: { parent: path.parent, field: path.parentField },
1616
- fieldChange,
1617
- localCrossFieldKeys: [],
1618
- childId: nodeId,
1619
- });
1955
+ if ((0, index_js_2.isDetachedUpPathRoot)(path)) {
1956
+ props.rootNodes.nodeChanges.set([path.detachedNodeId.major, (0, index_js_3.brand)(path.detachedNodeId.minor)], nodeId);
1957
+ return makeModularChangeset({
1958
+ rootNodes: props.rootNodes,
1959
+ nodeChanges: props.nodeChanges,
1960
+ nodeToParent: props.nodeToParent,
1961
+ crossFieldKeys: props.crossFieldKeys,
1962
+ maxId: props.idAllocator.getMaxId(),
1963
+ revisions: [{ revision: props.revision }],
1964
+ });
1965
+ }
1966
+ else {
1967
+ const fieldChangeset = genericFieldKind_js_1.genericFieldKind.changeHandler.editor.buildChildChanges([
1968
+ [path.parentIndex, nodeId],
1969
+ ]);
1970
+ const fieldChange = {
1971
+ fieldKind: genericFieldKind_js_1.genericFieldKind.identifier,
1972
+ change: fieldChangeset,
1973
+ };
1974
+ return buildModularChangesetFromField({
1975
+ ...props,
1976
+ path: { parent: path.parent, field: path.parentField },
1977
+ fieldChange,
1978
+ localCrossFieldKeys: [],
1979
+ childId: nodeId,
1980
+ });
1981
+ }
1982
+ }
1983
+ function renameTableFromRenameDescriptions(renames) {
1984
+ const table = newRootTable();
1985
+ for (const rename of renames) {
1986
+ addNodeRename(table, rename.oldId, rename.newId, rename.count, rename.detachLocation);
1987
+ }
1988
+ return table;
1620
1989
  }
1621
1990
  function getRevInfoFromTaggedChanges(changes) {
1622
1991
  let maxId = -1;
@@ -1633,18 +2002,6 @@ function getRevInfoFromTaggedChanges(changes) {
1633
2002
  }
1634
2003
  }
1635
2004
  }
1636
- const rolledBackRevisions = [];
1637
- for (const info of revInfos) {
1638
- if (info.rollbackOf !== undefined) {
1639
- rolledBackRevisions.push(info.rollbackOf);
1640
- }
1641
- }
1642
- rolledBackRevisions.reverse();
1643
- for (const revision of rolledBackRevisions) {
1644
- if (!revisions.has(revision)) {
1645
- revInfos.push({ revision });
1646
- }
1647
- }
1648
2005
  return { maxId: (0, index_js_3.brand)(maxId), revInfos };
1649
2006
  }
1650
2007
  function revisionInfoFromTaggedChange(taggedChange) {
@@ -1661,15 +2018,16 @@ function revisionInfoFromTaggedChange(taggedChange) {
1661
2018
  }
1662
2019
  return revInfos;
1663
2020
  }
1664
- function fieldChangeFromId(fields, nodes, id) {
1665
- const fieldMap = fieldMapFromNodeId(fields, nodes, id.nodeId);
2021
+ function fieldChangeFromId(change, id) {
2022
+ const fieldId = normalizeFieldId(id, change.nodeAliases);
2023
+ const fieldMap = fieldMapFromNodeId(change.fieldChanges, change.nodeChanges, change.nodeAliases, fieldId.nodeId);
1666
2024
  return fieldMap.get(id.field) ?? (0, internal_1.fail)(0xb25 /* No field exists for the given ID */);
1667
2025
  }
1668
- function fieldMapFromNodeId(rootFieldMap, nodes, nodeId) {
2026
+ function fieldMapFromNodeId(rootFieldMap, nodes, aliases, nodeId) {
1669
2027
  if (nodeId === undefined) {
1670
2028
  return rootFieldMap;
1671
2029
  }
1672
- const node = nodeChangeFromId(nodes, nodeId);
2030
+ const node = nodeChangeFromId(nodes, aliases, nodeId);
1673
2031
  (0, internal_1.assert)(node.fieldChanges !== undefined, 0x9c9 /* Expected node to have field changes */);
1674
2032
  return node.fieldChanges;
1675
2033
  }
@@ -1682,8 +2040,9 @@ function rebasedFieldIdFromBaseId(table, baseId) {
1682
2040
  function rebasedNodeIdFromBaseNodeId(table, baseId) {
1683
2041
  return (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(table.baseToRebasedNodeId, baseId) ?? baseId;
1684
2042
  }
1685
- function nodeChangeFromId(nodes, id) {
1686
- const node = (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(nodes, id);
2043
+ function nodeChangeFromId(nodes, aliases, id) {
2044
+ const normalizedId = normalizeNodeId(id, aliases);
2045
+ const node = (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(nodes, normalizedId);
1687
2046
  (0, internal_1.assert)(node !== undefined, 0x9ca /* Unknown node ID */);
1688
2047
  return node;
1689
2048
  }
@@ -1691,12 +2050,20 @@ function fieldIdFromFieldIdKey([revision, localId, field]) {
1691
2050
  const nodeId = localId === undefined ? undefined : { revision, localId };
1692
2051
  return { nodeId, field };
1693
2052
  }
2053
+ function fieldIdKeyFromFieldId(fieldId) {
2054
+ return [fieldId.nodeId?.revision, fieldId.nodeId?.localId, fieldId.field];
2055
+ }
1694
2056
  function cloneNodeChangeset(nodeChangeset) {
1695
2057
  if (nodeChangeset.fieldChanges !== undefined) {
1696
2058
  return { ...nodeChangeset, fieldChanges: new Map(nodeChangeset.fieldChanges) };
1697
2059
  }
1698
2060
  return { ...nodeChangeset };
1699
2061
  }
2062
+ function replaceNodeLocationRevision(location, replacer) {
2063
+ return location.field === undefined
2064
+ ? { root: replacer.getUpdatedAtomId(location.root) }
2065
+ : { field: replaceFieldIdRevision(location.field, replacer) };
2066
+ }
1700
2067
  function replaceFieldIdRevision(fieldId, replacer) {
1701
2068
  if (fieldId.nodeId === undefined) {
1702
2069
  return fieldId;
@@ -1706,17 +2073,34 @@ function replaceFieldIdRevision(fieldId, replacer) {
1706
2073
  nodeId: replacer.getUpdatedAtomId(fieldId.nodeId),
1707
2074
  };
1708
2075
  }
1709
- function getParentFieldId(changeset, nodeId) {
1710
- const parentId = (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(changeset.nodeToParent, nodeId);
1711
- (0, internal_1.assert)(parentId !== undefined, 0x9cb /* Parent field should be defined */);
1712
- return normalizeFieldId(parentId, changeset.nodeAliases);
2076
+ function getNodeParent(changeset, nodeId) {
2077
+ const normalizedNodeId = normalizeNodeId(nodeId, changeset.nodeAliases);
2078
+ const location = (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(changeset.nodeToParent, normalizedNodeId);
2079
+ (0, internal_1.assert)(location !== undefined, 0x9cb /* Parent field should be defined */);
2080
+ if (location.field !== undefined) {
2081
+ return { field: normalizeFieldId(location.field, changeset.nodeAliases) };
2082
+ }
2083
+ return location;
1713
2084
  }
1714
- exports.getParentFieldId = getParentFieldId;
2085
+ exports.getNodeParent = getNodeParent;
1715
2086
  function getFieldsForCrossFieldKey(changeset, key, count) {
1716
2087
  return changeset.crossFieldKeys
1717
2088
  .getAll(key, count)
1718
2089
  .map(({ value: fieldId }) => normalizeFieldId(fieldId, changeset.nodeAliases));
1719
2090
  }
2091
+ function getFirstFieldForCrossFieldKey(changeset, key, count) {
2092
+ const result = changeset.crossFieldKeys.getFirst(key, count);
2093
+ if (result.value === undefined) {
2094
+ return result;
2095
+ }
2096
+ return { ...result, value: normalizeFieldId(result.value, changeset.nodeAliases) };
2097
+ }
2098
+ function normalizeNodeLocation(location, nodeAliases) {
2099
+ if (location.field !== undefined) {
2100
+ return { field: normalizeFieldId(location.field, nodeAliases) };
2101
+ }
2102
+ return location;
2103
+ }
1720
2104
  // This is only exported for use in test utilities.
1721
2105
  function normalizeFieldId(fieldId, nodeAliases) {
1722
2106
  return fieldId.nodeId === undefined
@@ -1729,6 +2113,7 @@ exports.normalizeFieldId = normalizeFieldId;
1729
2113
  */
1730
2114
  function normalizeNodeId(nodeId, nodeAliases) {
1731
2115
  let currentId = nodeId;
2116
+ let cycleProbeId = nodeId;
1732
2117
  // eslint-disable-next-line no-constant-condition
1733
2118
  while (true) {
1734
2119
  const dealiased = (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(nodeAliases, currentId);
@@ -1736,12 +2121,501 @@ function normalizeNodeId(nodeId, nodeAliases) {
1736
2121
  return currentId;
1737
2122
  }
1738
2123
  currentId = dealiased;
2124
+ if (cycleProbeId !== undefined) {
2125
+ cycleProbeId = (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(nodeAliases, cycleProbeId);
2126
+ }
2127
+ if (cycleProbeId !== undefined) {
2128
+ cycleProbeId = (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(nodeAliases, cycleProbeId);
2129
+ }
2130
+ (0, internal_1.assert)(!(0, index_js_2.areEqualChangeAtomIdOpts)(cycleProbeId, currentId), "Alias cycle detected");
1739
2131
  }
1740
2132
  }
2133
+ exports.normalizeNodeId = normalizeNodeId;
1741
2134
  function hasConflicts(change) {
1742
2135
  return (change.constraintViolationCount ?? 0) > 0;
1743
2136
  }
1744
2137
  function areEqualFieldIds(a, b) {
1745
2138
  return (0, index_js_2.areEqualChangeAtomIdOpts)(a.nodeId, b.nodeId) && a.field === b.field;
1746
2139
  }
2140
+ function firstAttachIdFromDetachId(roots, detachId, count) {
2141
+ const result = roots.oldToNewId.getFirst(detachId, count);
2142
+ return { ...result, value: result.value ?? detachId };
2143
+ }
2144
+ function firstDetachIdFromAttachId(roots, attachId, count) {
2145
+ const result = roots.newToOldId.getFirst(attachId, count);
2146
+ return { ...result, start: attachId, value: result.value ?? attachId };
2147
+ }
2148
+ function rebaseCrossFieldKeys(sourceTable, movedDetaches, newDetachLocations) {
2149
+ const rebasedTable = sourceTable.clone();
2150
+ for (const entry of movedDetaches.entries()) {
2151
+ rebasedTable.delete({ ...entry.start, target: crossFieldQueries_js_1.CrossFieldTarget.Source }, entry.length);
2152
+ }
2153
+ for (const entry of newDetachLocations.entries()) {
2154
+ rebasedTable.set({ ...entry.start, target: crossFieldQueries_js_1.CrossFieldTarget.Source }, entry.length, entry.value);
2155
+ }
2156
+ return rebasedTable;
2157
+ }
2158
+ function newRootTable() {
2159
+ return {
2160
+ newToOldId: (0, index_js_2.newChangeAtomIdTransform)(),
2161
+ oldToNewId: (0, index_js_2.newChangeAtomIdTransform)(),
2162
+ nodeChanges: (0, index_js_3.newTupleBTree)(),
2163
+ detachLocations: (0, index_js_2.newChangeAtomIdRangeMap)(),
2164
+ outputDetachLocations: (0, index_js_2.newChangeAtomIdRangeMap)(),
2165
+ };
2166
+ }
2167
+ exports.newRootTable = newRootTable;
2168
+ function rebaseRoots(change, base, affectedBaseFields, nodesToRebase, rebasedNodeToParent, rebaseVersion) {
2169
+ const rebasedRoots = newRootTable();
2170
+ for (const renameEntry of change.rootNodes.oldToNewId.entries()) {
2171
+ rebaseRename(change.rootNodes, rebasedRoots, renameEntry, base, affectedBaseFields);
2172
+ }
2173
+ for (const [detachIdKey, nodeId] of change.rootNodes.nodeChanges.entries()) {
2174
+ const changes = base.rootNodes.nodeChanges.get(detachIdKey);
2175
+ if (changes !== undefined) {
2176
+ nodesToRebase.push([nodeId, changes]);
2177
+ }
2178
+ const detachId = (0, index_js_2.makeChangeAtomId)(detachIdKey[1], detachIdKey[0]);
2179
+ const attachId = firstAttachIdFromDetachId(base.rootNodes, detachId, 1).value;
2180
+ const baseAttachEntry = base.crossFieldKeys.getFirst({ target: crossFieldQueries_js_1.CrossFieldTarget.Destination, ...attachId }, 1);
2181
+ if (baseAttachEntry.value === undefined) {
2182
+ const renamedDetachId = firstAttachIdFromDetachId(base.rootNodes, detachId, 1).value;
2183
+ const baseOutputDetachLocation = base.rootNodes.outputDetachLocations.getFirst(renamedDetachId, 1).value;
2184
+ if (baseOutputDetachLocation !== undefined) {
2185
+ affectedBaseFields.set(fieldIdKeyFromFieldId(baseOutputDetachLocation), true);
2186
+ }
2187
+ const detachLocation = baseOutputDetachLocation ??
2188
+ change.rootNodes.detachLocations.getFirst(detachId, 1).value;
2189
+ // Note that `baseOutputDetachLocation` may contain a node ID from the base changeset.
2190
+ // We will replace the detach location entry with the node ID from the rebased changeset in `fixupRebasedDetachLocations`
2191
+ assignRootChange(rebasedRoots, rebasedNodeToParent, renamedDetachId, nodeId, detachLocation, rebaseVersion);
2192
+ }
2193
+ else {
2194
+ affectedBaseFields.set(fieldIdKeyFromFieldId(baseAttachEntry.value), true);
2195
+ rebasedNodeToParent.delete(detachIdKey);
2196
+ }
2197
+ }
2198
+ for (const entry of change.rootNodes.outputDetachLocations.entries()) {
2199
+ rebasedRoots.outputDetachLocations.set(entry.start, entry.length, entry.value);
2200
+ }
2201
+ return rebasedRoots;
2202
+ }
2203
+ function rebaseRename(newRoots, rebasedRoots, renameEntry, base, affectedBaseFields) {
2204
+ let count = renameEntry.length;
2205
+ const baseRenameEntry = firstAttachIdFromDetachId(base.rootNodes, renameEntry.start, count);
2206
+ count = baseRenameEntry.length;
2207
+ const baseAttachEntry = base.crossFieldKeys.getFirst({
2208
+ ...baseRenameEntry.value,
2209
+ target: crossFieldQueries_js_1.CrossFieldTarget.Destination,
2210
+ }, count);
2211
+ count = baseAttachEntry.length;
2212
+ if (baseAttachEntry.value === undefined) {
2213
+ const baseOutputDetachLocation = base.rootNodes.outputDetachLocations.getFirst(baseRenameEntry.value, 1).value;
2214
+ if (baseOutputDetachLocation !== undefined) {
2215
+ affectedBaseFields.set(fieldIdKeyFromFieldId(baseOutputDetachLocation), true);
2216
+ }
2217
+ const detachEntry = newRoots.detachLocations.getFirst(renameEntry.start, count);
2218
+ count = detachEntry.length;
2219
+ const detachLocation = baseOutputDetachLocation ?? detachEntry.value;
2220
+ // Note that `baseOutputDetachLocation` may contain a node ID from the base changeset.
2221
+ // We will replace the detach location entry with the node ID from the rebased changeset in `fixupRebasedDetachLocations`
2222
+ addNodeRename(rebasedRoots, baseRenameEntry.value, renameEntry.value, count, detachLocation);
2223
+ }
2224
+ else {
2225
+ // This rename represents an intention to detach these nodes.
2226
+ // The rebased change should have a detach in the field where the base change attaches the nodes,
2227
+ // so we need to ensure that field is processed.
2228
+ affectedBaseFields.set(fieldIdKeyFromFieldId(normalizeFieldId(baseAttachEntry.value, base.nodeAliases)), true);
2229
+ }
2230
+ const countRemaining = renameEntry.length - count;
2231
+ if (countRemaining > 0) {
2232
+ rebaseRename(newRoots, rebasedRoots, {
2233
+ start: (0, index_js_2.offsetChangeAtomId)(renameEntry.start, count),
2234
+ value: (0, index_js_2.offsetChangeAtomId)(renameEntry.value, count),
2235
+ length: countRemaining,
2236
+ }, base, affectedBaseFields);
2237
+ }
2238
+ }
2239
+ /**
2240
+ * For each root detach location, replaces any node ID from the base changeset
2241
+ * with the corresponding ID in the new changeset.
2242
+ */
2243
+ function fixupRebasedDetachLocations(table) {
2244
+ for (const { start, length, value: detachLocation, } of table.rebasedRootNodes.detachLocations.entries()) {
2245
+ const normalizedDetachLocation = normalizeFieldId(detachLocation, table.baseChange.nodeAliases);
2246
+ if (normalizedDetachLocation.nodeId !== undefined) {
2247
+ const rebasedNodeId = (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(table.baseToRebasedNodeId, normalizedDetachLocation.nodeId);
2248
+ if (rebasedNodeId !== undefined) {
2249
+ table.rebasedRootNodes.detachLocations.set(start, length, {
2250
+ ...normalizedDetachLocation,
2251
+ nodeId: rebasedNodeId,
2252
+ });
2253
+ }
2254
+ }
2255
+ }
2256
+ }
2257
+ function addNodesToCompose(table, id1, id2) {
2258
+ const normalizedId1 = normalizeNodeId(id1, table.baseChange.nodeAliases);
2259
+ const normalizedId2 = normalizeNodeId(id2, table.newChange.nodeAliases);
2260
+ if ((0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(table.newToBaseNodeId, normalizedId2) === undefined) {
2261
+ (0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(table.newToBaseNodeId, normalizedId2, normalizedId1);
2262
+ table.pendingCompositions.nodeIdsToCompose.push([normalizedId1, normalizedId2]);
2263
+ }
2264
+ }
2265
+ function composeRevInfos(revisions1, revisions2) {
2266
+ if (revisions1?.length === 1 &&
2267
+ revisions2?.length === 1 &&
2268
+ revisions1[0]?.revision === revisions2[0]?.revision) {
2269
+ // This is a special case where we are composing two changesets from the same transaction.
2270
+ // We return one of the input arrays to avoid duplicating revision entries.
2271
+ return revisions1;
2272
+ }
2273
+ const result = [...(revisions1 ?? []), ...(revisions2 ?? [])];
2274
+ return result;
2275
+ }
2276
+ function composeCrossFieldKeyTables(table1, table2, movedCrossFieldKeys, removedCrossFieldKeys) {
2277
+ const composedTable = index_js_3.RangeMap.union(table1, table2);
2278
+ for (const entry of movedCrossFieldKeys.entries()) {
2279
+ composedTable.set(entry.start, entry.length, entry.value);
2280
+ }
2281
+ for (const entry of removedCrossFieldKeys.entries()) {
2282
+ composedTable.delete(entry.start, entry.length);
2283
+ }
2284
+ return composedTable;
2285
+ }
2286
+ function composeRootTables(change1, change2, composedNodeToParent, movedCrossFieldKeys, removedCrossFieldKeys, pendingCompositions) {
2287
+ const composedTable = cloneRootTable(change1.rootNodes);
2288
+ for (const renameEntry of change2.rootNodes.oldToNewId.entries()) {
2289
+ composeRename(change1, change2, composedTable, renameEntry.start, renameEntry.value, renameEntry.length, movedCrossFieldKeys, removedCrossFieldKeys, pendingCompositions);
2290
+ }
2291
+ for (const [[revision2, id2], nodeId2] of change2.rootNodes.nodeChanges.entries()) {
2292
+ const detachId2 = { revision: revision2, localId: id2 };
2293
+ const detachId1 = firstDetachIdFromAttachId(change1.rootNodes, detachId2, 1).value;
2294
+ const nodeId1 = (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(change1.rootNodes.nodeChanges, detachId1);
2295
+ if (nodeId1 === undefined) {
2296
+ const fieldId = getFieldsForCrossFieldKey(change1, { ...detachId1, target: crossFieldQueries_js_1.CrossFieldTarget.Source }, 1)[0];
2297
+ if (fieldId === undefined) {
2298
+ assignRootChange(composedTable, composedNodeToParent, detachId1, nodeId2, change1.rootNodes.detachLocations.getFirst(detachId1, 1).value ??
2299
+ change2.rootNodes.detachLocations.getFirst(detachId2, 1).value, Math.max(change1.rebaseVersion, change2.rebaseVersion));
2300
+ }
2301
+ else {
2302
+ // In this case, this node is attached in the input context of change1,
2303
+ // and is represented in detachFieldId.
2304
+ pendingCompositions.affectedBaseFields.set([fieldId.nodeId?.revision, fieldId.nodeId?.localId, fieldId.field], true);
2305
+ }
2306
+ }
2307
+ else {
2308
+ pendingCompositions.nodeIdsToCompose.push([nodeId1, nodeId2]);
2309
+ }
2310
+ }
2311
+ for (const outputDetachEntry of change1.rootNodes.outputDetachLocations.entries()) {
2312
+ composeOutputDetachLocation(outputDetachEntry.start, outputDetachEntry.length, outputDetachEntry.value, change2, composedTable);
2313
+ }
2314
+ for (const entry of change2.rootNodes.outputDetachLocations.entries()) {
2315
+ composedTable.outputDetachLocations.set(entry.start, entry.length, entry.value);
2316
+ }
2317
+ return composedTable;
2318
+ }
2319
+ function composeOutputDetachLocation(outputDetachId1, count, detachLocation, change2, composedTable) {
2320
+ let countToProcess = count;
2321
+ const renameEntry = firstAttachIdFromDetachId(change2.rootNodes, outputDetachId1, countToProcess);
2322
+ countToProcess = renameEntry.length;
2323
+ const attachEntry = getFirstAttachField(change2.crossFieldKeys, renameEntry.value, countToProcess);
2324
+ countToProcess = attachEntry.length;
2325
+ composedTable.outputDetachLocations.delete(outputDetachId1, countToProcess);
2326
+ if (attachEntry.value === undefined) {
2327
+ // We update the key for the detach location to the renamed ID of the root in the composed output context.
2328
+ composedTable.outputDetachLocations.set(renameEntry.value, countToProcess, detachLocation);
2329
+ }
2330
+ else {
2331
+ // These nodes are attached by `change2` and thus attached in the composed output context,
2332
+ // so there should be no output detach location.
2333
+ }
2334
+ const countRemaining = count - countToProcess;
2335
+ if (countRemaining > 0) {
2336
+ composeOutputDetachLocation((0, index_js_2.offsetChangeAtomId)(outputDetachId1, countToProcess), countRemaining, detachLocation, change2, composedTable);
2337
+ }
2338
+ }
2339
+ function composeRename(change1, change2, mergedTable, oldId, newId, count, movedCrossFieldKeys, removedCrossFieldKeys, pendingCompositions) {
2340
+ let countToProcess = count;
2341
+ const detachEntry = getFirstDetachField(change1.crossFieldKeys, oldId, countToProcess);
2342
+ countToProcess = detachEntry.length;
2343
+ if (detachEntry.value === undefined) {
2344
+ // `change1` may also have a rename to `renameEntry.value`, in which case it must refer to a different node.
2345
+ // That node must have been attached by `change1` and detached by `change2`.
2346
+ // The final rename for that node will be created in `composeAttachDetach`.
2347
+ // We delete any such rename for now to avoid colliding with the rename currently being processed.
2348
+ deleteNodeRenameTo(mergedTable, newId, countToProcess);
2349
+ // The nodes were detached before `change`, so we append this rename.
2350
+ appendNodeRename(mergedTable, oldId, newId, countToProcess, change1.rootNodes, change2.rootNodes.detachLocations.getFirst(oldId, countToProcess).value);
2351
+ }
2352
+ else {
2353
+ // `change1` detached these nodes,
2354
+ // so we invalidate the detach location so that the detach's ID can be replaced with the new ID.
2355
+ pendingCompositions.affectedBaseFields.set(fieldIdKeyFromFieldId(detachEntry.value), true);
2356
+ if (!(0, index_js_2.areEqualChangeAtomIds)(oldId, newId)) {
2357
+ // `change1`'s detach will be replaced by `change2`'s detach, so we update the cross-field keys.
2358
+ removedCrossFieldKeys.set({ ...oldId, target: crossFieldQueries_js_1.CrossFieldTarget.Source }, countToProcess, true);
2359
+ }
2360
+ movedCrossFieldKeys.set({ ...newId, target: crossFieldQueries_js_1.CrossFieldTarget.Source }, countToProcess, detachEntry.value);
2361
+ }
2362
+ if (countToProcess < count) {
2363
+ composeRename(change1, change2, mergedTable, (0, index_js_2.offsetChangeAtomId)(oldId, countToProcess), (0, index_js_2.offsetChangeAtomId)(newId, countToProcess), count - countToProcess, movedCrossFieldKeys, removedCrossFieldKeys, pendingCompositions);
2364
+ }
2365
+ }
2366
+ function cloneRootTable(table) {
2367
+ return {
2368
+ oldToNewId: table.oldToNewId.clone(),
2369
+ newToOldId: table.newToOldId.clone(),
2370
+ nodeChanges: (0, index_js_3.brand)(table.nodeChanges.clone()),
2371
+ detachLocations: table.detachLocations.clone(),
2372
+ outputDetachLocations: table.outputDetachLocations.clone(),
2373
+ };
2374
+ }
2375
+ exports.cloneRootTable = cloneRootTable;
2376
+ function invertRootTable(change, isRollback) {
2377
+ const invertedRoots = newRootTable();
2378
+ for (const [[revision, localId], nodeId] of change.rootNodes.nodeChanges.entries()) {
2379
+ const detachId = { revision, localId };
2380
+ const renamedId = firstAttachIdFromDetachId(change.rootNodes, detachId, 1).value;
2381
+ // This checks whether `change` attaches this node.
2382
+ // If it does, the node is not detached in the input context of the inverse, and so should not be included in the root table.
2383
+ if (change.crossFieldKeys.getFirst({ ...renamedId, target: crossFieldQueries_js_1.CrossFieldTarget.Destination }, 1)
2384
+ .value === undefined) {
2385
+ assignRootChange(invertedRoots, undefined, renamedId, nodeId, change.rootNodes.detachLocations.getFirst(detachId, 1).value, change.rebaseVersion);
2386
+ }
2387
+ }
2388
+ if (isRollback) {
2389
+ // We only invert renames of nodes which are not attached or detached by this changeset.
2390
+ // When we invert an attach we will create a detach which incorporates the rename.
2391
+ for (const { start: oldId, value: newId, length, } of change.rootNodes.oldToNewId.entries()) {
2392
+ invertRename(change, invertedRoots, oldId, newId, length);
2393
+ }
2394
+ }
2395
+ return invertedRoots;
2396
+ }
2397
+ function invertRename(change, invertedRoots, oldId, newId, length) {
2398
+ for (const detachEntry of doesChangeDetachNodes(change.crossFieldKeys, newId, length)) {
2399
+ (0, internal_1.assert)(!detachEntry.value, "A changeset should not have a rename and detach for the same node.");
2400
+ }
2401
+ let countProcessed = length;
2402
+ const attachEntry = getFirstAttachField(change.crossFieldKeys, newId, countProcessed);
2403
+ countProcessed = attachEntry.length;
2404
+ if (attachEntry.value === undefined) {
2405
+ const outputDetachEntry = change.rootNodes.outputDetachLocations.getFirst(newId, countProcessed);
2406
+ countProcessed = outputDetachEntry.length;
2407
+ const inputDetachEntry = change.rootNodes.detachLocations.getFirst(oldId, countProcessed);
2408
+ countProcessed = inputDetachEntry.length;
2409
+ addNodeRename(invertedRoots, newId, oldId, countProcessed, outputDetachEntry.value ?? inputDetachEntry.value);
2410
+ }
2411
+ if (countProcessed < length) {
2412
+ invertRename(change, invertedRoots, (0, index_js_2.offsetChangeAtomId)(oldId, countProcessed), (0, index_js_2.offsetChangeAtomId)(newId, countProcessed), length - countProcessed);
2413
+ }
2414
+ }
2415
+ function doesChangeAttachNodes(table, id, count) {
2416
+ return table
2417
+ .getAll2({ ...id, target: crossFieldQueries_js_1.CrossFieldTarget.Destination }, count)
2418
+ .map((entry) => ({ ...entry, value: entry.value !== undefined }));
2419
+ }
2420
+ function doesChangeDetachNodes(table, id, count) {
2421
+ return table
2422
+ .getAll2({ ...id, target: crossFieldQueries_js_1.CrossFieldTarget.Source }, count)
2423
+ .map((entry) => ({ ...entry, value: entry.value !== undefined }));
2424
+ }
2425
+ function getFirstDetachField(table, id, count) {
2426
+ return table.getFirst({ target: crossFieldQueries_js_1.CrossFieldTarget.Source, ...id }, count);
2427
+ }
2428
+ exports.getFirstDetachField = getFirstDetachField;
2429
+ function getFirstAttachField(table, id, count) {
2430
+ return table.getFirst({ target: crossFieldQueries_js_1.CrossFieldTarget.Destination, ...id }, count);
2431
+ }
2432
+ exports.getFirstAttachField = getFirstAttachField;
2433
+ function addNodeRename(table, oldId, newId, count, detachLocation) {
2434
+ if ((0, index_js_2.areEqualChangeAtomIds)(oldId, newId)) {
2435
+ return;
2436
+ }
2437
+ for (const entry of table.oldToNewId.getAll2(oldId, count)) {
2438
+ (0, internal_1.assert)(entry.value === undefined ||
2439
+ (0, index_js_2.areEqualChangeAtomIds)(entry.value, (0, index_js_2.offsetChangeAtomId)(newId, entry.offset)), "Rename collision detected");
2440
+ }
2441
+ for (const entry of table.newToOldId.getAll2(newId, count)) {
2442
+ (0, internal_1.assert)(entry.value === undefined ||
2443
+ (0, index_js_2.areEqualChangeAtomIds)(entry.value, (0, index_js_2.offsetChangeAtomId)(oldId, entry.offset)), "Rename collision detected");
2444
+ }
2445
+ table.oldToNewId.set(oldId, count, newId);
2446
+ table.newToOldId.set(newId, count, oldId);
2447
+ if (detachLocation !== undefined) {
2448
+ table.detachLocations.set(oldId, count, detachLocation);
2449
+ }
2450
+ }
2451
+ exports.addNodeRename = addNodeRename;
2452
+ /**
2453
+ * Deletes any renames from `id`.
2454
+ */
2455
+ function deleteNodeRenameFrom(roots, id, count) {
2456
+ for (const entry of roots.oldToNewId.getAll(id, count)) {
2457
+ deleteNodeRenameEntry(roots, entry.start, entry.value, entry.length);
2458
+ }
2459
+ }
2460
+ /**
2461
+ * Deletes any renames to `id`.
2462
+ */
2463
+ function deleteNodeRenameTo(roots, id, count) {
2464
+ for (const entry of roots.newToOldId.getAll(id, count)) {
2465
+ deleteNodeRenameEntry(roots, entry.value, entry.start, entry.length);
2466
+ }
2467
+ }
2468
+ function appendNodeRename(composedTable, oldId, newId, count, change1Table, detachLocation) {
2469
+ let countToProcess = count;
2470
+ const rename1Entry = change1Table.newToOldId.getFirst(oldId, countToProcess);
2471
+ countToProcess = rename1Entry.length;
2472
+ if (rename1Entry.value !== undefined) {
2473
+ deleteNodeRenameFrom(composedTable, rename1Entry.value, countToProcess);
2474
+ }
2475
+ addNodeRename(composedTable, rename1Entry.value ?? oldId, newId, countToProcess, detachLocation);
2476
+ tryRemoveDetachLocation(composedTable, newId, countToProcess);
2477
+ if (countToProcess < count) {
2478
+ const countRemaining = count - countToProcess;
2479
+ appendNodeRename(composedTable, (0, index_js_2.offsetChangeAtomId)(oldId, countToProcess), (0, index_js_2.offsetChangeAtomId)(newId, countToProcess), countRemaining, change1Table, detachLocation);
2480
+ }
2481
+ }
2482
+ function tryRemoveDetachLocation(roots, rootId, count) {
2483
+ let countProcessed = count;
2484
+ const renameEntry = roots.oldToNewId.getFirst(rootId, countProcessed);
2485
+ countProcessed = renameEntry.length;
2486
+ const outputDetachEntry = roots.outputDetachLocations.getFirst(rootId, countProcessed);
2487
+ countProcessed = outputDetachEntry.length;
2488
+ const nodeChangeEntry = (0, changeAtomIdBTree_js_1.rangeQueryChangeAtomIdMap)(roots.nodeChanges, rootId, countProcessed);
2489
+ countProcessed = nodeChangeEntry.length;
2490
+ if (nodeChangeEntry.value === undefined &&
2491
+ renameEntry.value === undefined &&
2492
+ outputDetachEntry.value === undefined) {
2493
+ roots.detachLocations.delete(rootId, countProcessed);
2494
+ }
2495
+ const countRemaining = count - countProcessed;
2496
+ if (countRemaining > 0) {
2497
+ tryRemoveDetachLocation(roots, (0, index_js_2.offsetChangeAtomId)(rootId, countProcessed), countRemaining);
2498
+ }
2499
+ }
2500
+ /**
2501
+ * Deletes the entry renaming the ID range of length `count` from `oldId` to `newId`.
2502
+ * This function assumes that such an entry exists.
2503
+ */
2504
+ function deleteNodeRenameEntry(roots, oldId, newId, count) {
2505
+ roots.oldToNewId.delete(oldId, count);
2506
+ roots.newToOldId.delete(newId, count);
2507
+ }
2508
+ function replaceRootTableRevision(table, replacer, nodeAliases) {
2509
+ const oldToNewId = table.oldToNewId.mapEntries((id) => replacer.getUpdatedAtomId(id), (id) => replacer.getUpdatedAtomId(id));
2510
+ const newToOldId = table.newToOldId.mapEntries((id) => replacer.getUpdatedAtomId(id), (id) => replacer.getUpdatedAtomId(id));
2511
+ const nodeChanges = replaceIdMapRevisions(table.nodeChanges, replacer, (nodeId) => replacer.getUpdatedAtomId(normalizeNodeId(nodeId, nodeAliases)));
2512
+ const detachLocations = table.detachLocations.mapEntries((id) => replacer.getUpdatedAtomId(id), (fieldId) => replaceFieldIdRevision(normalizeFieldId(fieldId, nodeAliases), replacer));
2513
+ const outputDetachLocations = table.outputDetachLocations.mapEntries((id) => replacer.getUpdatedAtomId(id), (fieldId) => replaceFieldIdRevision(normalizeFieldId(fieldId, nodeAliases), replacer));
2514
+ return { oldToNewId, newToOldId, nodeChanges, detachLocations, outputDetachLocations };
2515
+ }
2516
+ function newDetachedEntryMap() {
2517
+ return new index_js_3.RangeMap(index_js_2.offsetChangeAtomId, index_js_2.subtractChangeAtomIds, offsetDetachedNodeEntry);
2518
+ }
2519
+ function offsetDetachedNodeEntry(entry, count) {
2520
+ (0, internal_1.assert)(count <= 1 || entry.nodeChange === undefined, "Cannot split an entry with a node change");
2521
+ return entry.detachId === undefined
2522
+ ? entry
2523
+ : { ...entry, detachId: (0, index_js_2.offsetChangeAtomId)(entry.detachId, count) };
2524
+ }
2525
+ function getFieldsWithRootMoves(roots, nodeAliases) {
2526
+ const fields = (0, index_js_3.newTupleBTree)();
2527
+ for (const { start: rootId, value: fieldId, length } of roots.detachLocations.entries()) {
2528
+ let isRootMoved = false;
2529
+ for (const renameEntry of roots.oldToNewId.getAll2(rootId, length)) {
2530
+ if (renameEntry.value !== undefined) {
2531
+ isRootMoved = true;
2532
+ }
2533
+ }
2534
+ for (const outputDetachEntry of roots.outputDetachLocations.getAll2(rootId, length)) {
2535
+ if (outputDetachEntry.value !== undefined) {
2536
+ isRootMoved = true;
2537
+ }
2538
+ }
2539
+ if (isRootMoved) {
2540
+ fields.set(fieldIdKeyFromFieldId(normalizeFieldId(fieldId, nodeAliases)), true);
2541
+ }
2542
+ }
2543
+ return fields;
2544
+ }
2545
+ function getFieldToRootChanges(roots, nodeAliases) {
2546
+ const fields = (0, index_js_3.newTupleBTree)();
2547
+ for (const rootIdKey of roots.nodeChanges.keys()) {
2548
+ const rootId = { revision: rootIdKey[0], localId: rootIdKey[1] };
2549
+ const detachLocation = roots.detachLocations.getFirst(rootId, 1).value;
2550
+ if (detachLocation !== undefined) {
2551
+ const fieldIdKey = fieldIdKeyFromFieldId(normalizeFieldId(detachLocation, nodeAliases));
2552
+ let rootsInField = fields.get(fieldIdKey);
2553
+ if (rootsInField === undefined) {
2554
+ rootsInField = [];
2555
+ fields.set(fieldIdKey, rootsInField);
2556
+ }
2557
+ rootsInField.push(rootId);
2558
+ }
2559
+ }
2560
+ return fields;
2561
+ }
2562
+ function muteRootChanges(roots) {
2563
+ return {
2564
+ oldToNewId: (0, index_js_2.newChangeAtomIdTransform)(),
2565
+ newToOldId: (0, index_js_2.newChangeAtomIdTransform)(),
2566
+ nodeChanges: (0, index_js_3.brand)(roots.nodeChanges.clone()),
2567
+ detachLocations: roots.detachLocations.clone(),
2568
+ outputDetachLocations: (0, index_js_2.newChangeAtomIdRangeMap)(),
2569
+ };
2570
+ }
2571
+ function validateChangeset(change, fieldKinds) {
2572
+ const unreachableNodes = (0, index_js_3.brand)(change.nodeToParent.clone());
2573
+ const unreachableCFKs = change.crossFieldKeys.clone();
2574
+ validateFieldChanges(fieldKinds, change, change.fieldChanges, undefined, unreachableNodes, unreachableCFKs);
2575
+ for (const [[revision, localId], node] of change.nodeChanges.entries()) {
2576
+ if (node.fieldChanges === undefined) {
2577
+ continue;
2578
+ }
2579
+ const nodeId = normalizeNodeId({ revision, localId }, change.nodeAliases);
2580
+ validateFieldChanges(fieldKinds, change, node.fieldChanges, nodeId, unreachableNodes, unreachableCFKs);
2581
+ }
2582
+ for (const [detachIdKey, nodeId] of change.rootNodes.nodeChanges.entries()) {
2583
+ const detachId = { revision: detachIdKey[0], localId: detachIdKey[1] };
2584
+ const location = getNodeParent(change, nodeId);
2585
+ (0, internal_1.assert)((0, index_js_2.areEqualChangeAtomIdOpts)(location.root, detachId), "Inconsistent node location");
2586
+ const normalizedNodeId = normalizeNodeId(nodeId, change.nodeAliases);
2587
+ unreachableNodes.delete([normalizedNodeId.revision, normalizedNodeId.localId]);
2588
+ const fieldChanges = nodeChangeFromId(change.nodeChanges, change.nodeAliases, nodeId).fieldChanges;
2589
+ if (fieldChanges !== undefined) {
2590
+ validateFieldChanges(fieldKinds, change, fieldChanges, normalizedNodeId, unreachableNodes, unreachableCFKs);
2591
+ }
2592
+ }
2593
+ (0, internal_1.assert)(unreachableNodes.size === 0, "Unreachable nodes found");
2594
+ (0, internal_1.assert)(unreachableCFKs.entries().length === 0, "Unreachable cross-field keys found");
2595
+ }
2596
+ exports.validateChangeset = validateChangeset;
2597
+ /**
2598
+ * Asserts that each node has a correct entry in `change.nodeToParent`,
2599
+ * and each cross field key has a correct entry in `change.crossFieldKeys`.
2600
+ * @returns the number of children found.
2601
+ */
2602
+ function validateFieldChanges(fieldKinds, change, fieldChanges, nodeParent, unreachableNodes, unreachableCFKs) {
2603
+ for (const [field, fieldChange] of fieldChanges.entries()) {
2604
+ const fieldId = { nodeId: nodeParent, field };
2605
+ const handler = getChangeHandler(fieldKinds, fieldChange.fieldKind);
2606
+ for (const [child, _index] of handler.getNestedChanges(fieldChange.change)) {
2607
+ const parentFieldId = getNodeParent(change, child);
2608
+ (0, internal_1.assert)(parentFieldId.field !== undefined && areEqualFieldIds(parentFieldId.field, fieldId), 0xa4e /* Inconsistent node parentage */);
2609
+ unreachableNodes.delete([child.revision, child.localId]);
2610
+ }
2611
+ for (const keyRange of handler.getCrossFieldKeys(fieldChange.change)) {
2612
+ const fields = getFieldsForCrossFieldKey(change, keyRange.key, keyRange.count);
2613
+ (0, internal_1.assert)(fields.length > 0, "Unregistered cross-field key");
2614
+ for (const fieldFromLookup of fields) {
2615
+ (0, internal_1.assert)(areEqualFieldIds(fieldFromLookup, fieldId), 0xa4f /* Inconsistent cross field keys */);
2616
+ }
2617
+ unreachableCFKs.delete(keyRange.key, keyRange.count);
2618
+ }
2619
+ }
2620
+ }
1747
2621
  //# sourceMappingURL=modularChangeFamily.js.map