@fluidframework/tree 2.83.0 → 2.90.0-378676

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