@fluidframework/tree 2.90.0-378676 → 2.90.0

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