@fluidframework/tree 2.1.0-276985 → 2.1.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 (583) hide show
  1. package/.eslintrc.cjs +7 -0
  2. package/.vscode/Tree.code-workspace +9 -2
  3. package/CHANGELOG.md +38 -0
  4. package/README.md +55 -12
  5. package/api-report/tree.alpha.api.md +2 -1
  6. package/api-report/tree.beta.api.md +2 -1
  7. package/api-report/tree.public.api.md +2 -1
  8. package/beta.d.ts +1 -1
  9. package/dist/beta.d.ts +1 -1
  10. package/dist/core/forest/editableForest.d.ts +6 -3
  11. package/dist/core/forest/editableForest.d.ts.map +1 -1
  12. package/dist/core/forest/editableForest.js +16 -4
  13. package/dist/core/forest/editableForest.js.map +1 -1
  14. package/dist/core/index.d.ts +1 -1
  15. package/dist/core/index.d.ts.map +1 -1
  16. package/dist/core/index.js +3 -1
  17. package/dist/core/index.js.map +1 -1
  18. package/dist/core/rebase/index.d.ts +1 -1
  19. package/dist/core/rebase/index.d.ts.map +1 -1
  20. package/dist/core/rebase/index.js +3 -1
  21. package/dist/core/rebase/index.js.map +1 -1
  22. package/dist/core/rebase/types.d.ts +2 -0
  23. package/dist/core/rebase/types.d.ts.map +1 -1
  24. package/dist/core/rebase/types.js +9 -1
  25. package/dist/core/rebase/types.js.map +1 -1
  26. package/dist/core/tree/anchorSet.d.ts +1 -0
  27. package/dist/core/tree/anchorSet.d.ts.map +1 -1
  28. package/dist/core/tree/anchorSet.js +13 -0
  29. package/dist/core/tree/anchorSet.js.map +1 -1
  30. package/dist/core/tree/detachedFieldIndex.d.ts +48 -11
  31. package/dist/core/tree/detachedFieldIndex.d.ts.map +1 -1
  32. package/dist/core/tree/detachedFieldIndex.js +144 -20
  33. package/dist/core/tree/detachedFieldIndex.js.map +1 -1
  34. package/dist/core/tree/detachedFieldIndexCodec.d.ts.map +1 -1
  35. package/dist/core/tree/detachedFieldIndexCodec.js +13 -4
  36. package/dist/core/tree/detachedFieldIndexCodec.js.map +1 -1
  37. package/dist/core/tree/detachedFieldIndexFormat.d.ts +1 -1
  38. package/dist/core/tree/detachedFieldIndexFormat.d.ts.map +1 -1
  39. package/dist/core/tree/detachedFieldIndexFormat.js.map +1 -1
  40. package/dist/core/tree/detachedFieldIndexTypes.d.ts +39 -4
  41. package/dist/core/tree/detachedFieldIndexTypes.d.ts.map +1 -1
  42. package/dist/core/tree/detachedFieldIndexTypes.js.map +1 -1
  43. package/dist/core/tree/index.d.ts +2 -1
  44. package/dist/core/tree/index.d.ts.map +1 -1
  45. package/dist/core/tree/index.js.map +1 -1
  46. package/dist/core/tree/visitDelta.d.ts +3 -1
  47. package/dist/core/tree/visitDelta.d.ts.map +1 -1
  48. package/dist/core/tree/visitDelta.js +31 -15
  49. package/dist/core/tree/visitDelta.js.map +1 -1
  50. package/dist/core/tree/visitorUtils.d.ts +3 -3
  51. package/dist/core/tree/visitorUtils.d.ts.map +1 -1
  52. package/dist/core/tree/visitorUtils.js +4 -4
  53. package/dist/core/tree/visitorUtils.js.map +1 -1
  54. package/dist/events/events.d.ts +4 -1
  55. package/dist/events/events.d.ts.map +1 -1
  56. package/dist/events/events.js.map +1 -1
  57. package/dist/feature-libraries/default-schema/defaultEditBuilder.js +1 -1
  58. package/dist/feature-libraries/default-schema/defaultEditBuilder.js.map +1 -1
  59. package/dist/feature-libraries/default-schema/defaultFieldKinds.d.ts.map +1 -1
  60. package/dist/feature-libraries/default-schema/defaultFieldKinds.js +1 -0
  61. package/dist/feature-libraries/default-schema/defaultFieldKinds.js.map +1 -1
  62. package/dist/feature-libraries/editableTreeBinder.js +1 -1
  63. package/dist/feature-libraries/editableTreeBinder.js.map +1 -1
  64. package/dist/feature-libraries/flex-map-tree/mapTreeNode.d.ts +1 -10
  65. package/dist/feature-libraries/flex-map-tree/mapTreeNode.d.ts.map +1 -1
  66. package/dist/feature-libraries/flex-map-tree/mapTreeNode.js +0 -72
  67. package/dist/feature-libraries/flex-map-tree/mapTreeNode.js.map +1 -1
  68. package/dist/feature-libraries/flex-tree/flexTreeTypes.d.ts +1 -51
  69. package/dist/feature-libraries/flex-tree/flexTreeTypes.d.ts.map +1 -1
  70. package/dist/feature-libraries/flex-tree/flexTreeTypes.js +0 -2
  71. package/dist/feature-libraries/flex-tree/flexTreeTypes.js.map +1 -1
  72. package/dist/feature-libraries/flex-tree/index.d.ts +3 -2
  73. package/dist/feature-libraries/flex-tree/index.d.ts.map +1 -1
  74. package/dist/feature-libraries/flex-tree/index.js +5 -1
  75. package/dist/feature-libraries/flex-tree/index.js.map +1 -1
  76. package/dist/feature-libraries/flex-tree/lazyEntity.d.ts +1 -2
  77. package/dist/feature-libraries/flex-tree/lazyEntity.d.ts.map +1 -1
  78. package/dist/feature-libraries/flex-tree/lazyEntity.js.map +1 -1
  79. package/dist/feature-libraries/flex-tree/lazyField.d.ts +1 -6
  80. package/dist/feature-libraries/flex-tree/lazyField.d.ts.map +1 -1
  81. package/dist/feature-libraries/flex-tree/lazyField.js +11 -32
  82. package/dist/feature-libraries/flex-tree/lazyField.js.map +1 -1
  83. package/dist/feature-libraries/flex-tree/lazyNode.d.ts +1 -5
  84. package/dist/feature-libraries/flex-tree/lazyNode.d.ts.map +1 -1
  85. package/dist/feature-libraries/flex-tree/lazyNode.js +0 -30
  86. package/dist/feature-libraries/flex-tree/lazyNode.js.map +1 -1
  87. package/dist/feature-libraries/forest-summary/forestSummarizer.d.ts.map +1 -1
  88. package/dist/feature-libraries/forest-summary/forestSummarizer.js +1 -1
  89. package/dist/feature-libraries/forest-summary/forestSummarizer.js.map +1 -1
  90. package/dist/feature-libraries/index.d.ts +3 -3
  91. package/dist/feature-libraries/index.d.ts.map +1 -1
  92. package/dist/feature-libraries/index.js +6 -3
  93. package/dist/feature-libraries/index.js.map +1 -1
  94. package/dist/feature-libraries/modular-schema/crossFieldQueries.d.ts +11 -0
  95. package/dist/feature-libraries/modular-schema/crossFieldQueries.d.ts.map +1 -1
  96. package/dist/feature-libraries/modular-schema/crossFieldQueries.js.map +1 -1
  97. package/dist/feature-libraries/modular-schema/discrepancies.d.ts +96 -0
  98. package/dist/feature-libraries/modular-schema/discrepancies.d.ts.map +1 -0
  99. package/dist/feature-libraries/modular-schema/discrepancies.js +264 -0
  100. package/dist/feature-libraries/modular-schema/discrepancies.js.map +1 -0
  101. package/dist/feature-libraries/modular-schema/fieldChangeHandler.d.ts +9 -2
  102. package/dist/feature-libraries/modular-schema/fieldChangeHandler.d.ts.map +1 -1
  103. package/dist/feature-libraries/modular-schema/fieldChangeHandler.js.map +1 -1
  104. package/dist/feature-libraries/modular-schema/genericFieldKind.d.ts.map +1 -1
  105. package/dist/feature-libraries/modular-schema/genericFieldKind.js +3 -0
  106. package/dist/feature-libraries/modular-schema/genericFieldKind.js.map +1 -1
  107. package/dist/feature-libraries/modular-schema/index.d.ts +2 -1
  108. package/dist/feature-libraries/modular-schema/index.d.ts.map +1 -1
  109. package/dist/feature-libraries/modular-schema/index.js +3 -1
  110. package/dist/feature-libraries/modular-schema/index.js.map +1 -1
  111. package/dist/feature-libraries/modular-schema/modularChangeCodecs.d.ts.map +1 -1
  112. package/dist/feature-libraries/modular-schema/modularChangeCodecs.js +42 -26
  113. package/dist/feature-libraries/modular-schema/modularChangeCodecs.js.map +1 -1
  114. package/dist/feature-libraries/modular-schema/modularChangeFamily.d.ts +51 -2
  115. package/dist/feature-libraries/modular-schema/modularChangeFamily.d.ts.map +1 -1
  116. package/dist/feature-libraries/modular-schema/modularChangeFamily.js +827 -245
  117. package/dist/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
  118. package/dist/feature-libraries/modular-schema/modularChangeFormat.d.ts.map +1 -1
  119. package/dist/feature-libraries/modular-schema/modularChangeFormat.js +2 -0
  120. package/dist/feature-libraries/modular-schema/modularChangeFormat.js.map +1 -1
  121. package/dist/feature-libraries/modular-schema/modularChangeTypes.d.ts +44 -1
  122. package/dist/feature-libraries/modular-schema/modularChangeTypes.d.ts.map +1 -1
  123. package/dist/feature-libraries/modular-schema/modularChangeTypes.js.map +1 -1
  124. package/dist/feature-libraries/node-key/index.d.ts +0 -1
  125. package/dist/feature-libraries/node-key/index.d.ts.map +1 -1
  126. package/dist/feature-libraries/node-key/index.js +1 -3
  127. package/dist/feature-libraries/node-key/index.js.map +1 -1
  128. package/dist/feature-libraries/object-forest/objectForest.d.ts +3 -2
  129. package/dist/feature-libraries/object-forest/objectForest.d.ts.map +1 -1
  130. package/dist/feature-libraries/object-forest/objectForest.js +5 -4
  131. package/dist/feature-libraries/object-forest/objectForest.js.map +1 -1
  132. package/dist/feature-libraries/optional-field/optionalField.d.ts.map +1 -1
  133. package/dist/feature-libraries/optional-field/optionalField.js +1 -0
  134. package/dist/feature-libraries/optional-field/optionalField.js.map +1 -1
  135. package/dist/feature-libraries/sequence-field/index.d.ts +1 -1
  136. package/dist/feature-libraries/sequence-field/index.d.ts.map +1 -1
  137. package/dist/feature-libraries/sequence-field/index.js +1 -2
  138. package/dist/feature-libraries/sequence-field/index.js.map +1 -1
  139. package/dist/feature-libraries/sequence-field/invert.js +1 -1
  140. package/dist/feature-libraries/sequence-field/invert.js.map +1 -1
  141. package/dist/feature-libraries/sequence-field/rebase.js +6 -1
  142. package/dist/feature-libraries/sequence-field/rebase.js.map +1 -1
  143. package/dist/feature-libraries/sequence-field/sequenceFieldChangeHandler.d.ts.map +1 -1
  144. package/dist/feature-libraries/sequence-field/sequenceFieldChangeHandler.js +1 -0
  145. package/dist/feature-libraries/sequence-field/sequenceFieldChangeHandler.js.map +1 -1
  146. package/dist/feature-libraries/sequence-field/utils.d.ts +2 -17
  147. package/dist/feature-libraries/sequence-field/utils.d.ts.map +1 -1
  148. package/dist/feature-libraries/sequence-field/utils.js +31 -39
  149. package/dist/feature-libraries/sequence-field/utils.js.map +1 -1
  150. package/dist/feature-libraries/typed-schema/typedTreeSchema.d.ts +1 -0
  151. package/dist/feature-libraries/typed-schema/typedTreeSchema.d.ts.map +1 -1
  152. package/dist/feature-libraries/typed-schema/typedTreeSchema.js +2 -0
  153. package/dist/feature-libraries/typed-schema/typedTreeSchema.js.map +1 -1
  154. package/dist/index.d.ts +1 -1
  155. package/dist/index.d.ts.map +1 -1
  156. package/dist/index.js.map +1 -1
  157. package/dist/packageVersion.d.ts +1 -1
  158. package/dist/packageVersion.d.ts.map +1 -1
  159. package/dist/packageVersion.js +1 -1
  160. package/dist/packageVersion.js.map +1 -1
  161. package/dist/public.d.ts +1 -1
  162. package/dist/shared-tree/schematizingTreeView.d.ts +4 -2
  163. package/dist/shared-tree/schematizingTreeView.d.ts.map +1 -1
  164. package/dist/shared-tree/schematizingTreeView.js +240 -184
  165. package/dist/shared-tree/schematizingTreeView.js.map +1 -1
  166. package/dist/shared-tree/sharedTree.d.ts +5 -1
  167. package/dist/shared-tree/sharedTree.d.ts.map +1 -1
  168. package/dist/shared-tree/sharedTree.js +157 -90
  169. package/dist/shared-tree/sharedTree.js.map +1 -1
  170. package/dist/shared-tree/sharedTreeChangeEnricher.js +1 -1
  171. package/dist/shared-tree/sharedTreeChangeEnricher.js.map +1 -1
  172. package/dist/shared-tree/treeApi.js +1 -1
  173. package/dist/shared-tree/treeApi.js.map +1 -1
  174. package/dist/shared-tree/treeCheckout.d.ts +10 -1
  175. package/dist/shared-tree/treeCheckout.d.ts.map +1 -1
  176. package/dist/shared-tree/treeCheckout.js +47 -3
  177. package/dist/shared-tree/treeCheckout.js.map +1 -1
  178. package/dist/shared-tree/treeView.d.ts.map +1 -1
  179. package/dist/shared-tree/treeView.js +7 -3
  180. package/dist/shared-tree/treeView.js.map +1 -1
  181. package/dist/shared-tree-core/branch.d.ts +6 -0
  182. package/dist/shared-tree-core/branch.d.ts.map +1 -1
  183. package/dist/shared-tree-core/branch.js +3 -0
  184. package/dist/shared-tree-core/branch.js.map +1 -1
  185. package/dist/shared-tree-core/sharedTreeCore.d.ts +8 -6
  186. package/dist/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
  187. package/dist/shared-tree-core/sharedTreeCore.js +271 -209
  188. package/dist/shared-tree-core/sharedTreeCore.js.map +1 -1
  189. package/dist/simple-tree/arrayNode.d.ts +4 -0
  190. package/dist/simple-tree/arrayNode.d.ts.map +1 -1
  191. package/dist/simple-tree/arrayNode.js +36 -19
  192. package/dist/simple-tree/arrayNode.js.map +1 -1
  193. package/dist/simple-tree/index.d.ts +3 -3
  194. package/dist/simple-tree/index.d.ts.map +1 -1
  195. package/dist/simple-tree/index.js +2 -1
  196. package/dist/simple-tree/index.js.map +1 -1
  197. package/dist/simple-tree/leafNodeSchema.d.ts +22 -1
  198. package/dist/simple-tree/leafNodeSchema.d.ts.map +1 -1
  199. package/dist/simple-tree/leafNodeSchema.js +2 -1
  200. package/dist/simple-tree/leafNodeSchema.js.map +1 -1
  201. package/dist/simple-tree/mapNode.d.ts.map +1 -1
  202. package/dist/simple-tree/mapNode.js.map +1 -1
  203. package/dist/simple-tree/objectNode.d.ts.map +1 -1
  204. package/dist/simple-tree/objectNode.js +2 -1
  205. package/dist/simple-tree/objectNode.js.map +1 -1
  206. package/dist/simple-tree/proxies.d.ts.map +1 -1
  207. package/dist/simple-tree/proxies.js +9 -25
  208. package/dist/simple-tree/proxies.js.map +1 -1
  209. package/dist/simple-tree/proxyBinding.d.ts +4 -0
  210. package/dist/simple-tree/proxyBinding.d.ts.map +1 -1
  211. package/dist/simple-tree/proxyBinding.js +23 -1
  212. package/dist/simple-tree/proxyBinding.js.map +1 -1
  213. package/dist/simple-tree/schemaFactory.d.ts +16 -1
  214. package/dist/simple-tree/schemaFactory.d.ts.map +1 -1
  215. package/dist/simple-tree/schemaFactory.js +32 -4
  216. package/dist/simple-tree/schemaFactory.js.map +1 -1
  217. package/dist/simple-tree/schemaTypes.d.ts +36 -1
  218. package/dist/simple-tree/schemaTypes.d.ts.map +1 -1
  219. package/dist/simple-tree/schemaTypes.js.map +1 -1
  220. package/dist/simple-tree/toFlexSchema.d.ts +2 -2
  221. package/dist/simple-tree/toFlexSchema.d.ts.map +1 -1
  222. package/dist/simple-tree/toFlexSchema.js +3 -2
  223. package/dist/simple-tree/toFlexSchema.js.map +1 -1
  224. package/dist/simple-tree/tree.d.ts +4 -1
  225. package/dist/simple-tree/tree.d.ts.map +1 -1
  226. package/dist/simple-tree/tree.js +48 -1
  227. package/dist/simple-tree/tree.js.map +1 -1
  228. package/dist/simple-tree/treeNodeApi.d.ts +2 -75
  229. package/dist/simple-tree/treeNodeApi.d.ts.map +1 -1
  230. package/dist/simple-tree/treeNodeApi.js +17 -25
  231. package/dist/simple-tree/treeNodeApi.js.map +1 -1
  232. package/dist/simple-tree/treeNodeKernel.d.ts +26 -0
  233. package/dist/simple-tree/treeNodeKernel.d.ts.map +1 -0
  234. package/dist/simple-tree/treeNodeKernel.js +83 -0
  235. package/dist/simple-tree/treeNodeKernel.js.map +1 -0
  236. package/dist/simple-tree/types.d.ts +95 -3
  237. package/dist/simple-tree/types.d.ts.map +1 -1
  238. package/dist/simple-tree/types.js +120 -21
  239. package/dist/simple-tree/types.js.map +1 -1
  240. package/dist/util/breakable.d.ts +83 -0
  241. package/dist/util/breakable.d.ts.map +1 -0
  242. package/dist/util/breakable.js +178 -0
  243. package/dist/util/breakable.js.map +1 -0
  244. package/dist/util/index.d.ts +3 -2
  245. package/dist/util/index.d.ts.map +1 -1
  246. package/dist/util/index.js +9 -2
  247. package/dist/util/index.js.map +1 -1
  248. package/dist/util/nestedMap.d.ts +17 -3
  249. package/dist/util/nestedMap.d.ts.map +1 -1
  250. package/dist/util/nestedMap.js +21 -1
  251. package/dist/util/nestedMap.js.map +1 -1
  252. package/dist/util/utils.d.ts +7 -0
  253. package/dist/util/utils.d.ts.map +1 -1
  254. package/dist/util/utils.js +15 -1
  255. package/dist/util/utils.js.map +1 -1
  256. package/internal.d.ts +1 -1
  257. package/lib/beta.d.ts +1 -1
  258. package/lib/core/forest/editableForest.d.ts +6 -3
  259. package/lib/core/forest/editableForest.d.ts.map +1 -1
  260. package/lib/core/forest/editableForest.js +17 -5
  261. package/lib/core/forest/editableForest.js.map +1 -1
  262. package/lib/core/index.d.ts +1 -1
  263. package/lib/core/index.d.ts.map +1 -1
  264. package/lib/core/index.js +1 -1
  265. package/lib/core/index.js.map +1 -1
  266. package/lib/core/rebase/index.d.ts +1 -1
  267. package/lib/core/rebase/index.d.ts.map +1 -1
  268. package/lib/core/rebase/index.js +1 -1
  269. package/lib/core/rebase/index.js.map +1 -1
  270. package/lib/core/rebase/types.d.ts +2 -0
  271. package/lib/core/rebase/types.d.ts.map +1 -1
  272. package/lib/core/rebase/types.js +7 -1
  273. package/lib/core/rebase/types.js.map +1 -1
  274. package/lib/core/tree/anchorSet.d.ts +1 -0
  275. package/lib/core/tree/anchorSet.d.ts.map +1 -1
  276. package/lib/core/tree/anchorSet.js +13 -0
  277. package/lib/core/tree/anchorSet.js.map +1 -1
  278. package/lib/core/tree/detachedFieldIndex.d.ts +48 -11
  279. package/lib/core/tree/detachedFieldIndex.d.ts.map +1 -1
  280. package/lib/core/tree/detachedFieldIndex.js +145 -21
  281. package/lib/core/tree/detachedFieldIndex.js.map +1 -1
  282. package/lib/core/tree/detachedFieldIndexCodec.d.ts.map +1 -1
  283. package/lib/core/tree/detachedFieldIndexCodec.js +13 -4
  284. package/lib/core/tree/detachedFieldIndexCodec.js.map +1 -1
  285. package/lib/core/tree/detachedFieldIndexFormat.d.ts +1 -1
  286. package/lib/core/tree/detachedFieldIndexFormat.d.ts.map +1 -1
  287. package/lib/core/tree/detachedFieldIndexFormat.js.map +1 -1
  288. package/lib/core/tree/detachedFieldIndexTypes.d.ts +39 -4
  289. package/lib/core/tree/detachedFieldIndexTypes.d.ts.map +1 -1
  290. package/lib/core/tree/detachedFieldIndexTypes.js.map +1 -1
  291. package/lib/core/tree/index.d.ts +2 -1
  292. package/lib/core/tree/index.d.ts.map +1 -1
  293. package/lib/core/tree/index.js.map +1 -1
  294. package/lib/core/tree/visitDelta.d.ts +3 -1
  295. package/lib/core/tree/visitDelta.d.ts.map +1 -1
  296. package/lib/core/tree/visitDelta.js +31 -15
  297. package/lib/core/tree/visitDelta.js.map +1 -1
  298. package/lib/core/tree/visitorUtils.d.ts +3 -3
  299. package/lib/core/tree/visitorUtils.d.ts.map +1 -1
  300. package/lib/core/tree/visitorUtils.js +4 -4
  301. package/lib/core/tree/visitorUtils.js.map +1 -1
  302. package/lib/events/events.d.ts +4 -1
  303. package/lib/events/events.d.ts.map +1 -1
  304. package/lib/events/events.js.map +1 -1
  305. package/lib/feature-libraries/default-schema/defaultEditBuilder.js +1 -1
  306. package/lib/feature-libraries/default-schema/defaultEditBuilder.js.map +1 -1
  307. package/lib/feature-libraries/default-schema/defaultFieldKinds.d.ts.map +1 -1
  308. package/lib/feature-libraries/default-schema/defaultFieldKinds.js +1 -0
  309. package/lib/feature-libraries/default-schema/defaultFieldKinds.js.map +1 -1
  310. package/lib/feature-libraries/editableTreeBinder.js +1 -1
  311. package/lib/feature-libraries/editableTreeBinder.js.map +1 -1
  312. package/lib/feature-libraries/flex-map-tree/mapTreeNode.d.ts +1 -10
  313. package/lib/feature-libraries/flex-map-tree/mapTreeNode.d.ts.map +1 -1
  314. package/lib/feature-libraries/flex-map-tree/mapTreeNode.js +2 -74
  315. package/lib/feature-libraries/flex-map-tree/mapTreeNode.js.map +1 -1
  316. package/lib/feature-libraries/flex-tree/flexTreeTypes.d.ts +1 -51
  317. package/lib/feature-libraries/flex-tree/flexTreeTypes.d.ts.map +1 -1
  318. package/lib/feature-libraries/flex-tree/flexTreeTypes.js +0 -2
  319. package/lib/feature-libraries/flex-tree/flexTreeTypes.js.map +1 -1
  320. package/lib/feature-libraries/flex-tree/index.d.ts +3 -2
  321. package/lib/feature-libraries/flex-tree/index.d.ts.map +1 -1
  322. package/lib/feature-libraries/flex-tree/index.js +2 -1
  323. package/lib/feature-libraries/flex-tree/index.js.map +1 -1
  324. package/lib/feature-libraries/flex-tree/lazyEntity.d.ts +1 -2
  325. package/lib/feature-libraries/flex-tree/lazyEntity.d.ts.map +1 -1
  326. package/lib/feature-libraries/flex-tree/lazyEntity.js.map +1 -1
  327. package/lib/feature-libraries/flex-tree/lazyField.d.ts +1 -6
  328. package/lib/feature-libraries/flex-tree/lazyField.d.ts.map +1 -1
  329. package/lib/feature-libraries/flex-tree/lazyField.js +13 -34
  330. package/lib/feature-libraries/flex-tree/lazyField.js.map +1 -1
  331. package/lib/feature-libraries/flex-tree/lazyNode.d.ts +1 -5
  332. package/lib/feature-libraries/flex-tree/lazyNode.d.ts.map +1 -1
  333. package/lib/feature-libraries/flex-tree/lazyNode.js +3 -33
  334. package/lib/feature-libraries/flex-tree/lazyNode.js.map +1 -1
  335. package/lib/feature-libraries/forest-summary/forestSummarizer.d.ts.map +1 -1
  336. package/lib/feature-libraries/forest-summary/forestSummarizer.js +1 -1
  337. package/lib/feature-libraries/forest-summary/forestSummarizer.js.map +1 -1
  338. package/lib/feature-libraries/index.d.ts +3 -3
  339. package/lib/feature-libraries/index.d.ts.map +1 -1
  340. package/lib/feature-libraries/index.js +3 -3
  341. package/lib/feature-libraries/index.js.map +1 -1
  342. package/lib/feature-libraries/modular-schema/crossFieldQueries.d.ts +11 -0
  343. package/lib/feature-libraries/modular-schema/crossFieldQueries.d.ts.map +1 -1
  344. package/lib/feature-libraries/modular-schema/crossFieldQueries.js.map +1 -1
  345. package/lib/feature-libraries/modular-schema/discrepancies.d.ts +96 -0
  346. package/lib/feature-libraries/modular-schema/discrepancies.d.ts.map +1 -0
  347. package/lib/feature-libraries/modular-schema/discrepancies.js +260 -0
  348. package/lib/feature-libraries/modular-schema/discrepancies.js.map +1 -0
  349. package/lib/feature-libraries/modular-schema/fieldChangeHandler.d.ts +9 -2
  350. package/lib/feature-libraries/modular-schema/fieldChangeHandler.d.ts.map +1 -1
  351. package/lib/feature-libraries/modular-schema/fieldChangeHandler.js.map +1 -1
  352. package/lib/feature-libraries/modular-schema/genericFieldKind.d.ts.map +1 -1
  353. package/lib/feature-libraries/modular-schema/genericFieldKind.js +3 -0
  354. package/lib/feature-libraries/modular-schema/genericFieldKind.js.map +1 -1
  355. package/lib/feature-libraries/modular-schema/index.d.ts +2 -1
  356. package/lib/feature-libraries/modular-schema/index.d.ts.map +1 -1
  357. package/lib/feature-libraries/modular-schema/index.js +1 -0
  358. package/lib/feature-libraries/modular-schema/index.js.map +1 -1
  359. package/lib/feature-libraries/modular-schema/modularChangeCodecs.d.ts.map +1 -1
  360. package/lib/feature-libraries/modular-schema/modularChangeCodecs.js +42 -26
  361. package/lib/feature-libraries/modular-schema/modularChangeCodecs.js.map +1 -1
  362. package/lib/feature-libraries/modular-schema/modularChangeFamily.d.ts +51 -2
  363. package/lib/feature-libraries/modular-schema/modularChangeFamily.d.ts.map +1 -1
  364. package/lib/feature-libraries/modular-schema/modularChangeFamily.js +826 -247
  365. package/lib/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
  366. package/lib/feature-libraries/modular-schema/modularChangeFormat.d.ts.map +1 -1
  367. package/lib/feature-libraries/modular-schema/modularChangeFormat.js +2 -0
  368. package/lib/feature-libraries/modular-schema/modularChangeFormat.js.map +1 -1
  369. package/lib/feature-libraries/modular-schema/modularChangeTypes.d.ts +44 -1
  370. package/lib/feature-libraries/modular-schema/modularChangeTypes.d.ts.map +1 -1
  371. package/lib/feature-libraries/modular-schema/modularChangeTypes.js.map +1 -1
  372. package/lib/feature-libraries/node-key/index.d.ts +0 -1
  373. package/lib/feature-libraries/node-key/index.d.ts.map +1 -1
  374. package/lib/feature-libraries/node-key/index.js +0 -1
  375. package/lib/feature-libraries/node-key/index.js.map +1 -1
  376. package/lib/feature-libraries/object-forest/objectForest.d.ts +3 -2
  377. package/lib/feature-libraries/object-forest/objectForest.d.ts.map +1 -1
  378. package/lib/feature-libraries/object-forest/objectForest.js +5 -4
  379. package/lib/feature-libraries/object-forest/objectForest.js.map +1 -1
  380. package/lib/feature-libraries/optional-field/optionalField.d.ts.map +1 -1
  381. package/lib/feature-libraries/optional-field/optionalField.js +1 -0
  382. package/lib/feature-libraries/optional-field/optionalField.js.map +1 -1
  383. package/lib/feature-libraries/sequence-field/index.d.ts +1 -1
  384. package/lib/feature-libraries/sequence-field/index.d.ts.map +1 -1
  385. package/lib/feature-libraries/sequence-field/index.js +1 -1
  386. package/lib/feature-libraries/sequence-field/index.js.map +1 -1
  387. package/lib/feature-libraries/sequence-field/invert.js +1 -1
  388. package/lib/feature-libraries/sequence-field/invert.js.map +1 -1
  389. package/lib/feature-libraries/sequence-field/rebase.js +6 -1
  390. package/lib/feature-libraries/sequence-field/rebase.js.map +1 -1
  391. package/lib/feature-libraries/sequence-field/sequenceFieldChangeHandler.d.ts.map +1 -1
  392. package/lib/feature-libraries/sequence-field/sequenceFieldChangeHandler.js +2 -1
  393. package/lib/feature-libraries/sequence-field/sequenceFieldChangeHandler.js.map +1 -1
  394. package/lib/feature-libraries/sequence-field/utils.d.ts +2 -17
  395. package/lib/feature-libraries/sequence-field/utils.d.ts.map +1 -1
  396. package/lib/feature-libraries/sequence-field/utils.js +31 -39
  397. package/lib/feature-libraries/sequence-field/utils.js.map +1 -1
  398. package/lib/feature-libraries/typed-schema/typedTreeSchema.d.ts +1 -0
  399. package/lib/feature-libraries/typed-schema/typedTreeSchema.d.ts.map +1 -1
  400. package/lib/feature-libraries/typed-schema/typedTreeSchema.js +4 -2
  401. package/lib/feature-libraries/typed-schema/typedTreeSchema.js.map +1 -1
  402. package/lib/index.d.ts +1 -1
  403. package/lib/index.d.ts.map +1 -1
  404. package/lib/index.js.map +1 -1
  405. package/lib/packageVersion.d.ts +1 -1
  406. package/lib/packageVersion.d.ts.map +1 -1
  407. package/lib/packageVersion.js +1 -1
  408. package/lib/packageVersion.js.map +1 -1
  409. package/lib/public.d.ts +1 -1
  410. package/lib/shared-tree/schematizingTreeView.d.ts +4 -2
  411. package/lib/shared-tree/schematizingTreeView.d.ts.map +1 -1
  412. package/lib/shared-tree/schematizingTreeView.js +242 -185
  413. package/lib/shared-tree/schematizingTreeView.js.map +1 -1
  414. package/lib/shared-tree/sharedTree.d.ts +5 -1
  415. package/lib/shared-tree/sharedTree.d.ts.map +1 -1
  416. package/lib/shared-tree/sharedTree.js +158 -90
  417. package/lib/shared-tree/sharedTree.js.map +1 -1
  418. package/lib/shared-tree/sharedTreeChangeEnricher.js +1 -1
  419. package/lib/shared-tree/sharedTreeChangeEnricher.js.map +1 -1
  420. package/lib/shared-tree/treeApi.js +1 -1
  421. package/lib/shared-tree/treeApi.js.map +1 -1
  422. package/lib/shared-tree/treeCheckout.d.ts +10 -1
  423. package/lib/shared-tree/treeCheckout.d.ts.map +1 -1
  424. package/lib/shared-tree/treeCheckout.js +47 -3
  425. package/lib/shared-tree/treeCheckout.js.map +1 -1
  426. package/lib/shared-tree/treeView.d.ts.map +1 -1
  427. package/lib/shared-tree/treeView.js +4 -0
  428. package/lib/shared-tree/treeView.js.map +1 -1
  429. package/lib/shared-tree-core/branch.d.ts +6 -0
  430. package/lib/shared-tree-core/branch.d.ts.map +1 -1
  431. package/lib/shared-tree-core/branch.js +3 -0
  432. package/lib/shared-tree-core/branch.js.map +1 -1
  433. package/lib/shared-tree-core/sharedTreeCore.d.ts +8 -6
  434. package/lib/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
  435. package/lib/shared-tree-core/sharedTreeCore.js +273 -210
  436. package/lib/shared-tree-core/sharedTreeCore.js.map +1 -1
  437. package/lib/simple-tree/arrayNode.d.ts +4 -0
  438. package/lib/simple-tree/arrayNode.d.ts.map +1 -1
  439. package/lib/simple-tree/arrayNode.js +39 -22
  440. package/lib/simple-tree/arrayNode.js.map +1 -1
  441. package/lib/simple-tree/index.d.ts +3 -3
  442. package/lib/simple-tree/index.d.ts.map +1 -1
  443. package/lib/simple-tree/index.js +1 -1
  444. package/lib/simple-tree/index.js.map +1 -1
  445. package/lib/simple-tree/leafNodeSchema.d.ts +22 -1
  446. package/lib/simple-tree/leafNodeSchema.d.ts.map +1 -1
  447. package/lib/simple-tree/leafNodeSchema.js +1 -1
  448. package/lib/simple-tree/leafNodeSchema.js.map +1 -1
  449. package/lib/simple-tree/mapNode.d.ts.map +1 -1
  450. package/lib/simple-tree/mapNode.js.map +1 -1
  451. package/lib/simple-tree/objectNode.d.ts.map +1 -1
  452. package/lib/simple-tree/objectNode.js +3 -2
  453. package/lib/simple-tree/objectNode.js.map +1 -1
  454. package/lib/simple-tree/proxies.d.ts.map +1 -1
  455. package/lib/simple-tree/proxies.js +9 -25
  456. package/lib/simple-tree/proxies.js.map +1 -1
  457. package/lib/simple-tree/proxyBinding.d.ts +4 -0
  458. package/lib/simple-tree/proxyBinding.d.ts.map +1 -1
  459. package/lib/simple-tree/proxyBinding.js +19 -0
  460. package/lib/simple-tree/proxyBinding.js.map +1 -1
  461. package/lib/simple-tree/schemaFactory.d.ts +16 -1
  462. package/lib/simple-tree/schemaFactory.d.ts.map +1 -1
  463. package/lib/simple-tree/schemaFactory.js +30 -3
  464. package/lib/simple-tree/schemaFactory.js.map +1 -1
  465. package/lib/simple-tree/schemaTypes.d.ts +36 -1
  466. package/lib/simple-tree/schemaTypes.d.ts.map +1 -1
  467. package/lib/simple-tree/schemaTypes.js.map +1 -1
  468. package/lib/simple-tree/toFlexSchema.d.ts +2 -2
  469. package/lib/simple-tree/toFlexSchema.d.ts.map +1 -1
  470. package/lib/simple-tree/toFlexSchema.js +3 -2
  471. package/lib/simple-tree/toFlexSchema.js.map +1 -1
  472. package/lib/simple-tree/tree.d.ts +4 -1
  473. package/lib/simple-tree/tree.d.ts.map +1 -1
  474. package/lib/simple-tree/tree.js +44 -0
  475. package/lib/simple-tree/tree.js.map +1 -1
  476. package/lib/simple-tree/treeNodeApi.d.ts +2 -75
  477. package/lib/simple-tree/treeNodeApi.d.ts.map +1 -1
  478. package/lib/simple-tree/treeNodeApi.js +20 -28
  479. package/lib/simple-tree/treeNodeApi.js.map +1 -1
  480. package/lib/simple-tree/treeNodeKernel.d.ts +26 -0
  481. package/lib/simple-tree/treeNodeKernel.d.ts.map +1 -0
  482. package/lib/simple-tree/treeNodeKernel.js +79 -0
  483. package/lib/simple-tree/treeNodeKernel.js.map +1 -0
  484. package/lib/simple-tree/types.d.ts +95 -3
  485. package/lib/simple-tree/types.d.ts.map +1 -1
  486. package/lib/simple-tree/types.js +121 -22
  487. package/lib/simple-tree/types.js.map +1 -1
  488. package/lib/util/breakable.d.ts +83 -0
  489. package/lib/util/breakable.d.ts.map +1 -0
  490. package/lib/util/breakable.js +171 -0
  491. package/lib/util/breakable.js.map +1 -0
  492. package/lib/util/index.d.ts +3 -2
  493. package/lib/util/index.d.ts.map +1 -1
  494. package/lib/util/index.js +3 -2
  495. package/lib/util/index.js.map +1 -1
  496. package/lib/util/nestedMap.d.ts +17 -3
  497. package/lib/util/nestedMap.d.ts.map +1 -1
  498. package/lib/util/nestedMap.js +19 -0
  499. package/lib/util/nestedMap.js.map +1 -1
  500. package/lib/util/utils.d.ts +7 -0
  501. package/lib/util/utils.d.ts.map +1 -1
  502. package/lib/util/utils.js +13 -0
  503. package/lib/util/utils.js.map +1 -1
  504. package/package.json +29 -27
  505. package/src/core/forest/editableForest.ts +25 -4
  506. package/src/core/index.ts +2 -0
  507. package/src/core/rebase/index.ts +2 -0
  508. package/src/core/rebase/types.ts +17 -0
  509. package/src/core/tree/anchorSet.ts +14 -0
  510. package/src/core/tree/detachedFieldIndex.ts +217 -35
  511. package/src/core/tree/detachedFieldIndexCodec.ts +17 -8
  512. package/src/core/tree/detachedFieldIndexFormat.ts +1 -1
  513. package/src/core/tree/detachedFieldIndexTypes.ts +41 -5
  514. package/src/core/tree/index.ts +2 -1
  515. package/src/core/tree/visitDelta.ts +58 -16
  516. package/src/core/tree/visitorUtils.ts +7 -4
  517. package/src/events/events.ts +4 -2
  518. package/src/feature-libraries/default-schema/defaultEditBuilder.ts +1 -1
  519. package/src/feature-libraries/default-schema/defaultFieldKinds.ts +1 -0
  520. package/src/feature-libraries/editableTreeBinder.ts +1 -1
  521. package/src/feature-libraries/flex-map-tree/mapTreeNode.ts +1 -95
  522. package/src/feature-libraries/flex-tree/flexTreeTypes.ts +0 -62
  523. package/src/feature-libraries/flex-tree/index.ts +7 -2
  524. package/src/feature-libraries/flex-tree/lazyEntity.ts +0 -3
  525. package/src/feature-libraries/flex-tree/lazyField.ts +15 -47
  526. package/src/feature-libraries/flex-tree/lazyNode.ts +1 -48
  527. package/src/feature-libraries/forest-summary/forestSummarizer.ts +1 -0
  528. package/src/feature-libraries/index.ts +4 -2
  529. package/src/feature-libraries/modular-schema/crossFieldQueries.ts +18 -0
  530. package/src/feature-libraries/modular-schema/discrepancies.ts +395 -0
  531. package/src/feature-libraries/modular-schema/fieldChangeHandler.ts +10 -2
  532. package/src/feature-libraries/modular-schema/genericFieldKind.ts +3 -0
  533. package/src/feature-libraries/modular-schema/index.ts +2 -0
  534. package/src/feature-libraries/modular-schema/modularChangeCodecs.ts +81 -35
  535. package/src/feature-libraries/modular-schema/modularChangeFamily.ts +1521 -444
  536. package/src/feature-libraries/modular-schema/modularChangeFormat.ts +2 -0
  537. package/src/feature-libraries/modular-schema/modularChangeTypes.ts +51 -0
  538. package/src/feature-libraries/node-key/index.ts +0 -1
  539. package/src/feature-libraries/object-forest/objectForest.ts +7 -3
  540. package/src/feature-libraries/optional-field/optionalField.ts +1 -0
  541. package/src/feature-libraries/sequence-field/index.ts +0 -2
  542. package/src/feature-libraries/sequence-field/invert.ts +1 -1
  543. package/src/feature-libraries/sequence-field/rebase.ts +7 -1
  544. package/src/feature-libraries/sequence-field/sequenceFieldChangeHandler.ts +2 -1
  545. package/src/feature-libraries/sequence-field/utils.ts +37 -85
  546. package/src/feature-libraries/typed-schema/typedTreeSchema.ts +10 -0
  547. package/src/index.ts +0 -1
  548. package/src/packageVersion.ts +1 -1
  549. package/src/shared-tree/schematizingTreeView.ts +6 -2
  550. package/src/shared-tree/sharedTree.ts +12 -1
  551. package/src/shared-tree/sharedTreeChangeEnricher.ts +1 -1
  552. package/src/shared-tree/treeApi.ts +1 -1
  553. package/src/shared-tree/treeCheckout.ts +60 -5
  554. package/src/shared-tree/treeView.ts +5 -0
  555. package/src/shared-tree-core/branch.ts +10 -0
  556. package/src/shared-tree-core/sharedTreeCore.ts +25 -6
  557. package/src/simple-tree/arrayNode.ts +50 -23
  558. package/src/simple-tree/index.ts +3 -3
  559. package/src/simple-tree/leafNodeSchema.ts +1 -1
  560. package/src/simple-tree/mapNode.ts +2 -2
  561. package/src/simple-tree/objectNode.ts +9 -3
  562. package/src/simple-tree/proxies.ts +10 -33
  563. package/src/simple-tree/proxyBinding.ts +23 -0
  564. package/src/simple-tree/schemaFactory.ts +37 -2
  565. package/src/simple-tree/schemaTypes.ts +36 -1
  566. package/src/simple-tree/toFlexSchema.ts +5 -4
  567. package/src/simple-tree/tree.ts +68 -4
  568. package/src/simple-tree/treeNodeApi.ts +29 -111
  569. package/src/simple-tree/treeNodeKernel.ts +91 -0
  570. package/src/simple-tree/types.ts +292 -31
  571. package/src/util/breakable.ts +214 -0
  572. package/src/util/index.ts +11 -0
  573. package/src/util/nestedMap.ts +33 -3
  574. package/src/util/utils.ts +17 -0
  575. package/dist/feature-libraries/node-key/nodeKeyIndex.d.ts +0 -41
  576. package/dist/feature-libraries/node-key/nodeKeyIndex.d.ts.map +0 -1
  577. package/dist/feature-libraries/node-key/nodeKeyIndex.js +0 -101
  578. package/dist/feature-libraries/node-key/nodeKeyIndex.js.map +0 -1
  579. package/lib/feature-libraries/node-key/nodeKeyIndex.d.ts +0 -41
  580. package/lib/feature-libraries/node-key/nodeKeyIndex.d.ts.map +0 -1
  581. package/lib/feature-libraries/node-key/nodeKeyIndex.js +0 -97
  582. package/lib/feature-libraries/node-key/nodeKeyIndex.js.map +0 -1
  583. package/src/feature-libraries/node-key/nodeKeyIndex.ts +0 -132
@@ -4,7 +4,7 @@
4
4
  * Licensed under the MIT License.
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.ModularEditBuilder = exports.getChangeHandler = exports.getFieldKind = exports.rebaseRevisionMetadataFromInfo = exports.intoDelta = exports.updateRefreshers = exports.relevantRemovedRoots = exports.ModularChangeFamily = void 0;
7
+ exports.newCrossFieldKeyTable = exports.getFieldsForCrossFieldKey = exports.getParentFieldId = exports.ModularEditBuilder = exports.getChangeHandler = exports.getFieldKind = exports.rebaseRevisionMetadataFromInfo = exports.intoDelta = exports.updateRefreshers = exports.relevantRemovedRoots = exports.ModularChangeFamily = void 0;
8
8
  const internal_1 = require("@fluidframework/core-utils/internal");
9
9
  const sorted_btree_es6_1 = require("@tylerbu/sorted-btree-es6");
10
10
  const index_js_1 = require("../../core/index.js");
@@ -37,27 +37,30 @@ class ModularChangeFamily {
37
37
  */
38
38
  normalizeFieldChanges(change1, change2, genId, revisionMetadata) {
39
39
  // TODO: Handle the case where changes have conflicting field kinds
40
- const kind = change1 !== undefined && change1.fieldKind !== genericFieldKind_js_1.genericFieldKind.identifier
40
+ const kind = change1.fieldKind !== genericFieldKind_js_1.genericFieldKind.identifier
41
41
  ? change1.fieldKind
42
- : change2?.fieldKind ?? genericFieldKind_js_1.genericFieldKind.identifier;
42
+ : change2.fieldKind;
43
43
  if (kind === genericFieldKind_js_1.genericFieldKind.identifier) {
44
- // All the changes are generic
44
+ // Both changes are generic
45
45
  return {
46
- fieldKind: genericFieldKind_js_1.genericFieldKind,
47
- change1: change1?.change,
48
- change2: change2?.change,
46
+ fieldKind: genericFieldKind_js_1.genericFieldKind.identifier,
47
+ changeHandler: genericFieldKind_js_1.genericFieldKind.changeHandler,
48
+ change1: change1.change,
49
+ change2: change2.change,
49
50
  };
50
51
  }
51
52
  const fieldKind = getFieldKind(this.fieldKinds, kind);
52
- const handler = fieldKind.changeHandler;
53
- const normalizedChange1 = this.normalizeFieldChange(change1, handler, genId, revisionMetadata);
54
- const normalizedChange2 = this.normalizeFieldChange(change2, handler, genId, revisionMetadata);
55
- return { fieldKind, change1: normalizedChange1, change2: normalizedChange2 };
53
+ const changeHandler = fieldKind.changeHandler;
54
+ const normalizedChange1 = this.normalizeFieldChange(change1, changeHandler, genId, revisionMetadata);
55
+ const normalizedChange2 = this.normalizeFieldChange(change2, changeHandler, genId, revisionMetadata);
56
+ return {
57
+ fieldKind: kind,
58
+ changeHandler,
59
+ change1: normalizedChange1,
60
+ change2: normalizedChange2,
61
+ };
56
62
  }
57
63
  normalizeFieldChange(fieldChange, handler, genId, revisionMetadata) {
58
- if (fieldChange === undefined) {
59
- return undefined;
60
- }
61
64
  if (fieldChange.fieldKind !== genericFieldKind_js_1.genericFieldKind.identifier) {
62
65
  return fieldChange.change;
63
66
  }
@@ -72,105 +75,224 @@ class ModularChangeFamily {
72
75
  compose(changes) {
73
76
  const { revInfos, maxId } = getRevInfoFromTaggedChanges(changes);
74
77
  const idState = { maxId };
75
- return changes.reduce((change1, change2) => (0, index_js_1.makeAnonChange)(this.composePair(change1, change2, revInfos, idState)), (0, index_js_1.makeAnonChange)({ fieldChanges: new Map(), nodeChanges: new Map() })).change;
78
+ if (changes.length === 0) {
79
+ return makeModularChangeset();
80
+ }
81
+ return changes.reduce((change1, change2) => (0, index_js_1.makeAnonChange)(this.composePair(change1, change2, revInfos, idState))).change;
76
82
  }
77
83
  composePair(change1, change2, revInfos, idState) {
78
- const genId = (0, index_js_2.idAllocatorFromState)(idState);
79
- const revisionMetadata = (0, index_js_1.revisionMetadataSourceFromInfo)(revInfos);
80
- const crossFieldTable = newComposeTable();
81
- const composedFields = this.composeFieldMaps(getActiveFieldChanges(change1.change), getActiveFieldChanges(change2.change), genId, crossFieldTable, revisionMetadata);
82
- const composedNodeChanges = new Map();
83
- for (const [id1, id2] of crossFieldTable.nodeIdPairs) {
84
- this.composeNodesById(change1.change.nodeChanges, change2.change.nodeChanges, composedNodeChanges, id1, id2, genId, crossFieldTable, revisionMetadata);
85
- }
86
- crossFieldTable.nodeIdPairs.length = 0;
87
- while (crossFieldTable.invalidatedFields.size > 0) {
88
- const fieldsToUpdate = crossFieldTable.invalidatedFields;
89
- crossFieldTable.invalidatedFields = new Set();
90
- for (const fieldChange of fieldsToUpdate) {
91
- const context = crossFieldTable.fieldToContext.get(fieldChange);
92
- (0, internal_1.assert)(context !== undefined, 0x8cc /* Should have context for every invalidated field */);
93
- const { change1: fieldChange1, change2: fieldChange2, composedChange } = context;
94
- const rebaser = getChangeHandler(this.fieldKinds, composedChange.fieldKind).rebaser;
95
- const composeNodes = (child1, child2) => {
96
- if (child2 !== undefined &&
97
- !(0, index_js_2.nestedSetContains)(crossFieldTable.nodeIds, child2.revision, child2.localId)) {
98
- crossFieldTable.nodeIdPairs.push([child1, child2]);
99
- if (child1 !== undefined && child2 !== undefined) {
100
- (0, index_js_2.addToNestedSet)(crossFieldTable.nodeIds, child2.revision, child2.localId);
101
- }
102
- }
103
- return child1 ?? child2 ?? (0, index_js_2.fail)("Should not compose two undefined nodes");
104
- };
105
- const amendedChange = rebaser.compose(fieldChange1, fieldChange2, composeNodes, genId, newCrossFieldManager(crossFieldTable, fieldChange, false), revisionMetadata);
106
- composedChange.change = (0, index_js_2.brand)(amendedChange);
107
- // Process any newly discovered nodes.
108
- for (const [taggedId1, taggedId2] of crossFieldTable.nodeIdPairs) {
109
- this.composeNodesById(change1.change.nodeChanges, change2.change.nodeChanges, composedNodeChanges, taggedId1, taggedId2, genId, crossFieldTable, revisionMetadata);
110
- }
111
- crossFieldTable.nodeIdPairs.length = 0;
112
- }
113
- }
84
+ const { fieldChanges, nodeChanges, nodeToParent, nodeAliases, crossFieldKeys } = this.composeAllFields(change1.change, change2.change, revInfos, idState);
114
85
  const { allBuilds, allDestroys, allRefreshers } = composeBuildsDestroysAndRefreshers([
115
86
  change1,
116
87
  change2,
117
88
  ]);
118
- return makeModularChangeset(this.pruneFieldMap(composedFields, composedNodeChanges), composedNodeChanges, idState.maxId, revInfos, undefined, allBuilds, allDestroys, allRefreshers);
89
+ return makeModularChangeset(this.pruneFieldMap(fieldChanges, nodeChanges), nodeChanges, nodeToParent, nodeAliases, crossFieldKeys, idState.maxId, revInfos, undefined, allBuilds, allDestroys, allRefreshers);
90
+ }
91
+ composeAllFields(change1, change2, revInfos, idState) {
92
+ if (hasConflicts(change1) && hasConflicts(change2)) {
93
+ return {
94
+ fieldChanges: new Map(),
95
+ nodeChanges: new Map(),
96
+ nodeToParent: new Map(),
97
+ nodeAliases: new Map(),
98
+ crossFieldKeys: newBTree(),
99
+ };
100
+ }
101
+ else if (hasConflicts(change1)) {
102
+ return change2;
103
+ }
104
+ else if (hasConflicts(change2)) {
105
+ return change1;
106
+ }
107
+ const genId = (0, index_js_2.idAllocatorFromState)(idState);
108
+ const revisionMetadata = (0, index_js_1.revisionMetadataSourceFromInfo)(revInfos);
109
+ const crossFieldTable = newComposeTable(change1, change2);
110
+ // We merge nodeChanges, nodeToParent, and nodeAliases from the two changesets.
111
+ // The merged tables will have correct entries for all nodes which are only referenced in one of the input changesets.
112
+ // During composeFieldMaps and processInvalidatedElements we will find all nodes referenced in both input changesets
113
+ // and adjust these tables as necessary.
114
+ // Note that when merging these tables we may encounter key collisions and will arbitrarily drop values in that case.
115
+ // A collision for a node ID means that that node is referenced in both changesets
116
+ // (since we assume that if two changesets use the same node ID they are referring to the same node),
117
+ // therefore all collisions will be addressed when processing the intersection of the changesets.
118
+ const composedNodeChanges = mergeNestedMaps(change1.nodeChanges, change2.nodeChanges);
119
+ const composedNodeToParent = mergeNestedMaps(change1.nodeToParent, change2.nodeToParent);
120
+ const composedNodeAliases = mergeNestedMaps(change1.nodeAliases, change2.nodeAliases);
121
+ const composedFields = this.composeFieldMaps(change1.fieldChanges, change2.fieldChanges, genId, crossFieldTable, revisionMetadata);
122
+ this.processInvalidatedElements(crossFieldTable, composedFields, composedNodeChanges, composedNodeToParent, composedNodeAliases, genId, revisionMetadata);
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 = mergeBTrees(change1.crossFieldKeys, change2.crossFieldKeys);
125
+ return {
126
+ fieldChanges: composedFields,
127
+ nodeChanges: composedNodeChanges,
128
+ nodeToParent: composedNodeToParent,
129
+ nodeAliases: composedNodeAliases,
130
+ crossFieldKeys: (0, index_js_2.brand)(composedCrossFieldKeys),
131
+ };
132
+ }
133
+ composeInvalidatedField(fieldChange, crossFieldTable, genId, revisionMetadata) {
134
+ const context = crossFieldTable.fieldToContext.get(fieldChange);
135
+ (0, internal_1.assert)(context !== undefined, 0x8cc /* Should have context for every invalidated field */);
136
+ const { change1: fieldChange1, change2: fieldChange2, composedChange } = context;
137
+ const rebaser = getChangeHandler(this.fieldKinds, composedChange.fieldKind).rebaser;
138
+ const composeNodes = (child1, child2) => {
139
+ if (child1 !== undefined &&
140
+ child2 !== undefined &&
141
+ (0, index_js_1.getFromChangeAtomIdMap)(crossFieldTable.newToBaseNodeId, child2) === undefined) {
142
+ (0, index_js_1.setInChangeAtomIdMap)(crossFieldTable.newToBaseNodeId, child2, child1);
143
+ crossFieldTable.pendingCompositions.nodeIdsToCompose.push([child1, child2]);
144
+ }
145
+ return child1 ?? child2 ?? (0, index_js_2.fail)("Should not compose two undefined nodes");
146
+ };
147
+ const amendedChange = rebaser.compose(fieldChange1, fieldChange2, composeNodes, genId, new ComposeManager(crossFieldTable, fieldChange, false), revisionMetadata);
148
+ composedChange.change = (0, index_js_2.brand)(amendedChange);
149
+ }
150
+ /**
151
+ * Updates everything in the composed output which may no longer be valid.
152
+ * This could be due to
153
+ * - discovering that two node changesets refer to the same node (`nodeIdsToCompose`)
154
+ * - a previously composed field being invalidated by a cross field effect (`invalidatedFields`)
155
+ * - a field which was copied directly from an input changeset being invalidated by a cross field effect
156
+ * (`affectedBaseFields` and `affectedNewFields`)
157
+ *
158
+ * Updating an element may invalidate further elements. This function runs until there is no more invalidation.
159
+ */
160
+ processInvalidatedElements(table, composedFields, composedNodes, composedNodeToParent, nodeAliases, genId, metadata) {
161
+ const pending = table.pendingCompositions;
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);
174
+ }
175
+ }
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);
181
+ }
182
+ }
183
+ /**
184
+ * Ensures that each field in `affectedFields` has been updated in the composition output.
185
+ * Any field which has already been composed is ignored.
186
+ * All other fields are optimistically assumed to not have any changes in the other input changeset.
187
+ *
188
+ * @param change - The changeset which contains the affected fields.
189
+ * This should be one of the two changesets being composed.
190
+ * @param areBaseFields - Whether the affected fields are part of the base changeset.
191
+ * If not, they are assumed to be part of the new changeset.
192
+ * @param affectedFields - The set of fields to process.
193
+ */
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);
198
+ if (table.fieldToContext.has(fieldChange) ||
199
+ table.newFieldToBaseField.has(fieldChange)) {
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;
204
+ }
205
+ const emptyChange = this.createEmptyFieldChange(fieldChange.fieldKind);
206
+ const [change1, change2] = areBaseFields
207
+ ? [fieldChange, emptyChange]
208
+ : [emptyChange, fieldChange];
209
+ const composedField = this.composeFieldChanges(change1, change2, genId, table, metadata);
210
+ if (fieldId.nodeId === undefined) {
211
+ composedFields.set(fieldId.field, composedField);
212
+ continue;
213
+ }
214
+ const nodeId = (0, index_js_1.getFromChangeAtomIdMap)(table.newToBaseNodeId, fieldId.nodeId) ?? fieldId.nodeId;
215
+ let nodeChangeset = nodeChangeFromId(composedNodes, nodeId);
216
+ if (!table.composedNodes.has(nodeChangeset)) {
217
+ nodeChangeset = cloneNodeChangeset(nodeChangeset);
218
+ (0, index_js_1.setInChangeAtomIdMap)(composedNodes, nodeId, nodeChangeset);
219
+ }
220
+ if (nodeChangeset.fieldChanges === undefined) {
221
+ nodeChangeset.fieldChanges = new Map();
222
+ }
223
+ nodeChangeset.fieldChanges.set(fieldId.field, composedField);
224
+ }
225
+ affectedFields.clear();
119
226
  }
120
227
  composeFieldMaps(change1, change2, genId, crossFieldTable, revisionMetadata) {
121
228
  const composedFields = new Map();
122
- const fields = new Set();
123
- for (const field of change1?.keys() ?? []) {
124
- fields.add(field);
125
- }
126
- for (const field of change2?.keys() ?? []) {
127
- fields.add(field);
128
- }
129
- for (const field of fields) {
130
- const fieldChange1 = change1?.get(field);
131
- const fieldChange2 = change2?.get(field);
132
- const { fieldKind, change1: normalizedFieldChange1, change2: normalizedFieldChange2, } = this.normalizeFieldChanges(fieldChange1, fieldChange2, genId, revisionMetadata);
133
- const manager = newCrossFieldManager(crossFieldTable, fieldChange1 ?? fieldChange2);
134
- const change1Normalized = normalizedFieldChange1 ?? fieldKind.changeHandler.createEmpty();
135
- const change2Normalized = normalizedFieldChange2 ?? fieldKind.changeHandler.createEmpty();
136
- const composedChange = fieldKind.changeHandler.rebaser.compose(change1Normalized, change2Normalized, (child1, child2) => {
137
- crossFieldTable.nodeIdPairs.push([child1, child2]);
138
- if (child2 !== undefined) {
139
- (0, index_js_2.addToNestedSet)(crossFieldTable.nodeIds, child2.revision, child2.localId);
140
- }
141
- return child1 ?? child2 ?? (0, index_js_2.fail)("Should not compose two undefined nodes");
142
- }, genId, manager, revisionMetadata);
143
- const composedField = {
144
- fieldKind: fieldKind.identifier,
145
- change: (0, index_js_2.brand)(composedChange),
146
- };
147
- const fieldKey = fieldChange1 ?? fieldChange2 ?? (0, index_js_2.fail)("At least one field should have changes");
148
- crossFieldTable.fieldToContext.set(fieldKey, {
149
- change1: change1Normalized,
150
- change2: change2Normalized,
151
- composedChange: composedField,
152
- });
153
- // TODO: Could optimize by checking that composedField is non-empty
229
+ if (change1 === undefined || change2 === undefined) {
230
+ return change1 ?? change2 ?? composedFields;
231
+ }
232
+ for (const [field, fieldChange1] of change1) {
233
+ const fieldChange2 = change2.get(field);
234
+ const composedField = fieldChange2 !== undefined
235
+ ? this.composeFieldChanges(fieldChange1, fieldChange2, genId, crossFieldTable, revisionMetadata)
236
+ : fieldChange1;
154
237
  composedFields.set(field, composedField);
155
238
  }
239
+ for (const [field, fieldChange2] of change2) {
240
+ if (change1 === undefined || !change1.has(field)) {
241
+ composedFields.set(field, fieldChange2);
242
+ }
243
+ }
156
244
  return composedFields;
157
245
  }
158
- composeNodesById(nodeChanges1, nodeChanges2, composedNodeChanges, id1, id2, idAllocator, crossFieldTable, revisionMetadata) {
159
- const nodeChangeset1 = id1 !== undefined
160
- ? (0, index_js_2.tryGetFromNestedMap)(nodeChanges1, id1.revision, id1.localId) ??
161
- (0, index_js_2.fail)("Unknown node ID")
162
- : {};
163
- const nodeChangeset2 = id2 !== undefined
164
- ? (0, index_js_2.tryGetFromNestedMap)(nodeChanges2, id2.revision, id2.localId) ??
165
- (0, index_js_2.fail)("Unknown node ID")
166
- : {};
246
+ /**
247
+ * Returns the composition of the two input fields.
248
+ *
249
+ * Any nodes in this field which were modified by both changesets
250
+ * will be added to `crossFieldTable.pendingCompositions.nodeIdsToCompose`.
251
+ *
252
+ * Any fields which had cross-field information sent to them as part of this field composition
253
+ * will be added to either `affectedBaseFields` or `affectedNewFields` in `crossFieldTable.pendingCompositions`.
254
+ *
255
+ * Any composed `FieldChange` which is invalidated by new cross-field information will be added to `crossFieldTable.invalidatedFields`.
256
+ */
257
+ composeFieldChanges(change1, change2, idAllocator, crossFieldTable, revisionMetadata) {
258
+ const { fieldKind, changeHandler, change1: change1Normalized, change2: change2Normalized, } = this.normalizeFieldChanges(change1, change2, idAllocator, revisionMetadata);
259
+ const manager = new ComposeManager(crossFieldTable, change1);
260
+ const composedChange = changeHandler.rebaser.compose(change1Normalized, change2Normalized, (child1, child2) => {
261
+ if (child1 !== undefined && child2 !== undefined) {
262
+ (0, index_js_1.setInChangeAtomIdMap)(crossFieldTable.newToBaseNodeId, child2, child1);
263
+ crossFieldTable.pendingCompositions.nodeIdsToCompose.push([child1, child2]);
264
+ }
265
+ return child1 ?? child2 ?? (0, index_js_2.fail)("Should not compose two undefined nodes");
266
+ }, idAllocator, manager, revisionMetadata);
267
+ const composedField = {
268
+ fieldKind,
269
+ change: (0, index_js_2.brand)(composedChange),
270
+ };
271
+ crossFieldTable.fieldToContext.set(change1, {
272
+ change1: change1Normalized,
273
+ change2: change2Normalized,
274
+ composedChange: composedField,
275
+ });
276
+ crossFieldTable.newFieldToBaseField.set(change2, change1);
277
+ return composedField;
278
+ }
279
+ composeNodesById(nodeChanges1, nodeChanges2, composedNodes, composedNodeToParent, nodeAliases, id1, id2, idAllocator, crossFieldTable, revisionMetadata) {
280
+ const nodeChangeset1 = nodeChangeFromId(nodeChanges1, id1);
281
+ const nodeChangeset2 = nodeChangeFromId(nodeChanges2, id2);
167
282
  const composedNodeChangeset = this.composeNodeChanges(nodeChangeset1, nodeChangeset2, idAllocator, crossFieldTable, revisionMetadata);
168
- const nodeId = id1 ?? id2 ?? (0, index_js_2.fail)("Should not compose two undefined node IDs");
169
- (0, index_js_2.setInNestedMap)(composedNodeChanges, nodeId.revision, nodeId.localId, composedNodeChangeset);
283
+ (0, index_js_1.setInChangeAtomIdMap)(composedNodes, id1, composedNodeChangeset);
284
+ if (!(0, index_js_1.areEqualChangeAtomIds)(id1, id2)) {
285
+ (0, index_js_2.deleteFromNestedMap)(composedNodes, id2.revision, id2.localId);
286
+ (0, index_js_2.deleteFromNestedMap)(composedNodeToParent, id2.revision, id2.localId);
287
+ (0, index_js_1.setInChangeAtomIdMap)(nodeAliases, id2, id1);
288
+ // We need to delete id1 to avoid forming a cycle in case id1 already had an alias.
289
+ (0, index_js_2.deleteFromNestedMap)(nodeAliases, id1.revision, id1.localId);
290
+ }
291
+ crossFieldTable.composedNodes.add(composedNodeChangeset);
170
292
  }
171
293
  composeNodeChanges(change1, change2, genId, crossFieldTable, revisionMetadata) {
172
- const nodeExistsConstraint = change1?.nodeExistsConstraint ?? change2?.nodeExistsConstraint;
173
- const composedFieldChanges = this.composeFieldMaps(change1?.fieldChanges, change2?.fieldChanges, genId, crossFieldTable, revisionMetadata);
294
+ const nodeExistsConstraint = change1.nodeExistsConstraint ?? change2.nodeExistsConstraint;
295
+ const composedFieldChanges = this.composeFieldMaps(change1.fieldChanges, change2.fieldChanges, genId, crossFieldTable, revisionMetadata);
174
296
  const composedNodeChange = {};
175
297
  if (composedFieldChanges.size > 0) {
176
298
  composedNodeChange.fieldChanges = composedFieldChanges;
@@ -193,23 +315,21 @@ class ModularChangeFamily {
193
315
  // Destroys only occur in rollback changesets, which are never inverted.
194
316
  (0, internal_1.assert)(change.change.destroys === undefined, 0x89a /* Unexpected destroys in change to invert */);
195
317
  if ((change.change.constraintViolationCount ?? 0) > 0) {
196
- return makeModularChangeset(undefined, undefined, change.change.maxId, [], undefined, undefined, destroys);
318
+ return makeModularChangeset(undefined, undefined, undefined, undefined, undefined, change.change.maxId, [], undefined, undefined, destroys);
197
319
  }
198
- const idState = { maxId: change.change.maxId ?? -1 };
199
- // This idState is used for the whole of the IdAllocator's lifetime, which allows
200
- // this function to read the updated idState.maxId after more IDs are allocated.
201
- // TODO: add a getMax function to IdAllocator to make for a clearer contract.
202
- const genId = (0, index_js_2.idAllocatorFromState)(idState);
320
+ const genId = (0, index_js_2.idAllocatorFromMaxId)(change.change.maxId ?? -1);
321
+ const invertedNodeToParent = cloneNestedMap(change.change.nodeToParent);
203
322
  const crossFieldTable = {
204
323
  ...newCrossFieldTable(),
205
324
  originalFieldToContext: new Map(),
325
+ invertedNodeToParent,
206
326
  };
207
327
  const { revInfos } = getRevInfoFromTaggedChanges([change]);
208
328
  const revisionMetadata = (0, index_js_1.revisionMetadataSourceFromInfo)(revInfos);
209
- const invertedFields = this.invertFieldMap(change.change.fieldChanges, isRollback, genId, crossFieldTable, revisionMetadata);
329
+ const invertedFields = this.invertFieldMap(change.change.fieldChanges, undefined, isRollback, genId, crossFieldTable, revisionMetadata);
210
330
  const invertedNodes = new Map();
211
331
  (0, index_js_2.forEachInNestedMap)(change.change.nodeChanges, (nodeChangeset, revision, localId) => {
212
- (0, index_js_2.setInNestedMap)(invertedNodes, revision, localId, this.invertNodeChange(nodeChangeset, isRollback, genId, crossFieldTable, revisionMetadata));
332
+ (0, index_js_2.setInNestedMap)(invertedNodes, revision, localId, this.invertNodeChange(nodeChangeset, { revision, localId }, isRollback, genId, crossFieldTable, revisionMetadata));
213
333
  });
214
334
  if (crossFieldTable.invalidatedFields.size > 0) {
215
335
  const fieldsToUpdate = crossFieldTable.invalidatedFields;
@@ -218,17 +338,19 @@ class ModularChangeFamily {
218
338
  const originalFieldChange = fieldChange.change;
219
339
  const context = crossFieldTable.originalFieldToContext.get(fieldChange);
220
340
  (0, internal_1.assert)(context !== undefined, 0x851 /* Should have context for every invalidated field */);
221
- const { invertedField } = context;
222
- const amendedChange = getChangeHandler(this.fieldKinds, fieldChange.fieldKind).rebaser.invert(originalFieldChange, isRollback, genId, newCrossFieldManager(crossFieldTable, fieldChange), revisionMetadata);
341
+ const { invertedField, fieldId } = context;
342
+ const amendedChange = getChangeHandler(this.fieldKinds, fieldChange.fieldKind).rebaser.invert(originalFieldChange, isRollback, genId, new InvertManager(crossFieldTable, fieldChange, fieldId), revisionMetadata);
223
343
  invertedField.change = (0, index_js_2.brand)(amendedChange);
224
344
  }
225
345
  }
226
- return makeModularChangeset(invertedFields, invertedNodes, idState.maxId, [], change.change.constraintViolationCount, undefined, destroys);
346
+ const crossFieldKeys = this.makeCrossFieldKeyTable(invertedFields, invertedNodes);
347
+ return makeModularChangeset(invertedFields, invertedNodes, invertedNodeToParent, change.change.nodeAliases, crossFieldKeys, genId.getMaxId(), [], change.change.constraintViolationCount, undefined, destroys);
227
348
  }
228
- invertFieldMap(changes, isRollback, genId, crossFieldTable, revisionMetadata) {
349
+ invertFieldMap(changes, parentId, isRollback, genId, crossFieldTable, revisionMetadata) {
229
350
  const invertedFields = new Map();
230
351
  for (const [field, fieldChange] of changes) {
231
- const manager = newCrossFieldManager(crossFieldTable, fieldChange);
352
+ const fieldId = { nodeId: parentId, field };
353
+ const manager = new InvertManager(crossFieldTable, fieldChange, fieldId);
232
354
  const invertedChange = getChangeHandler(this.fieldKinds, fieldChange.fieldKind).rebaser.invert(fieldChange.change, isRollback, genId, manager, revisionMetadata);
233
355
  const invertedFieldChange = {
234
356
  ...fieldChange,
@@ -236,15 +358,16 @@ class ModularChangeFamily {
236
358
  };
237
359
  invertedFields.set(field, invertedFieldChange);
238
360
  crossFieldTable.originalFieldToContext.set(fieldChange, {
361
+ fieldId,
239
362
  invertedField: invertedFieldChange,
240
363
  });
241
364
  }
242
365
  return invertedFields;
243
366
  }
244
- invertNodeChange(change, isRollback, genId, crossFieldTable, revisionMetadata) {
367
+ invertNodeChange(change, id, isRollback, genId, crossFieldTable, revisionMetadata) {
245
368
  const inverse = {};
246
369
  if (change.fieldChanges !== undefined) {
247
- inverse.fieldChanges = this.invertFieldMap(change.fieldChanges, isRollback, genId, crossFieldTable, revisionMetadata);
370
+ inverse.fieldChanges = this.invertFieldMap(change.fieldChanges, id, isRollback, genId, crossFieldTable, revisionMetadata);
248
371
  }
249
372
  return inverse;
250
373
  }
@@ -255,9 +378,15 @@ class ModularChangeFamily {
255
378
  const genId = (0, index_js_2.idAllocatorFromState)(idState);
256
379
  const crossFieldTable = {
257
380
  ...newCrossFieldTable(),
258
- fieldToContext: new Map(),
259
- rebasedNodeCache: new Map(),
381
+ newChange: change,
382
+ baseChange: over.change,
383
+ baseFieldToContext: new Map(),
384
+ baseToRebasedNodeId: new Map(),
385
+ rebasedFields: new Set(),
386
+ rebasedNodeToParent: cloneNestedMap(change.nodeToParent),
387
+ rebasedCrossFieldKeys: (0, index_js_2.brand)(change.crossFieldKeys.clone()),
260
388
  nodeIdPairs: [],
389
+ affectedBaseFields: newBTree(),
261
390
  };
262
391
  let constraintState = newConstraintState(change.constraintViolationCount ?? 0);
263
392
  const getBaseRevisions = () => revisionInfoFromTaggedChange(over).map((info) => info.revision);
@@ -266,108 +395,198 @@ class ModularChangeFamily {
266
395
  getRevisionToRebase: () => taggedChange.revision,
267
396
  getBaseRevisions,
268
397
  };
269
- const rebasedFields = this.rebaseFieldMap(change.fieldChanges, over.change.fieldChanges, genId, crossFieldTable, rebaseMetadata);
270
- const rebasedNodes = new Map();
271
- for (const [newId, baseId] of crossFieldTable.nodeIdPairs) {
272
- const newNodeChange = newId !== undefined
273
- ? (0, index_js_2.tryGetFromNestedMap)(change.nodeChanges, newId.revision, newId.localId)
274
- : undefined;
275
- const baseNodeChange = baseId !== undefined
276
- ? (0, index_js_2.tryGetFromNestedMap)(over.change.nodeChanges, baseId.revision, baseId.localId) ??
277
- (0, index_js_2.fail)("Unknown node ID")
278
- : {};
279
- const rebasedNode = this.rebaseNodeChange(newNodeChange, baseNodeChange, genId, crossFieldTable, rebaseMetadata);
280
- if (rebasedNode !== undefined) {
281
- const nodeId = newId ?? baseId ?? (0, index_js_2.fail)("Should not have two undefined IDs");
282
- (0, index_js_2.setInNestedMap)(rebasedNodes, nodeId.revision, nodeId.localId, rebasedNode);
283
- }
284
- }
398
+ const rebasedNodes = cloneNestedMap(change.nodeChanges);
399
+ const rebasedFields = this.rebaseIntersectingFields(crossFieldTable, rebasedNodes, genId, constraintState, rebaseMetadata);
400
+ this.rebaseFieldsWithoutNewChanges(rebasedFields, rebasedNodes, crossFieldTable, genId, rebaseMetadata);
285
401
  if (crossFieldTable.invalidatedFields.size > 0) {
286
402
  const fieldsToUpdate = crossFieldTable.invalidatedFields;
287
403
  crossFieldTable.invalidatedFields = new Set();
288
404
  constraintState = newConstraintState(change.constraintViolationCount ?? 0);
289
405
  for (const field of fieldsToUpdate) {
290
- // TODO: Should we copy the context table out before this loop?
291
- const context = crossFieldTable.fieldToContext.get(field);
406
+ const context = crossFieldTable.baseFieldToContext.get(field);
292
407
  (0, internal_1.assert)(context !== undefined, 0x852 /* Every field should have a context */);
293
- const { fieldKind, change1: fieldChangeset, change2: baseChangeset, } = this.normalizeFieldChanges(context.newChange, context.baseChange, genId, revisionMetadata);
294
- context.rebasedChange.change = fieldKind.changeHandler.rebaser.rebase(fieldChangeset, baseChangeset, (curr, base, existenceState) => curr ?? base, genId, newCrossFieldManager(crossFieldTable, field), rebaseMetadata);
408
+ const { changeHandler, change1: fieldChangeset, change2: baseChangeset, } = this.normalizeFieldChanges(context.newChange, context.baseChange, genId, revisionMetadata);
409
+ const rebaseChild = (curr, base) => {
410
+ if (curr !== undefined) {
411
+ return curr;
412
+ }
413
+ if (base !== undefined) {
414
+ for (const id of context.baseNodeIds) {
415
+ if ((0, index_js_1.areEqualChangeAtomIds)(base, id)) {
416
+ return base;
417
+ }
418
+ }
419
+ }
420
+ return undefined;
421
+ };
422
+ context.rebasedChange.change = (0, index_js_2.brand)(changeHandler.rebaser.rebase(fieldChangeset, baseChangeset, rebaseChild, genId, new RebaseManager(crossFieldTable, field, context.fieldId), rebaseMetadata));
295
423
  }
296
424
  }
297
425
  this.updateConstraintsForFields(rebasedFields, fieldChangeHandler_js_1.NodeAttachState.Attached, constraintState, rebasedNodes);
298
- return makeModularChangeset(this.pruneFieldMap(rebasedFields, rebasedNodes), rebasedNodes, idState.maxId, change.revisions, constraintState.violationCount, change.builds, change.destroys, change.refreshers);
426
+ return makeModularChangeset(this.pruneFieldMap(rebasedFields, rebasedNodes), rebasedNodes, crossFieldTable.rebasedNodeToParent, change.nodeAliases, crossFieldTable.rebasedCrossFieldKeys, idState.maxId, change.revisions, constraintState.violationCount, change.builds, change.destroys, change.refreshers);
299
427
  }
300
- rebaseFieldMap(change, over, genId, crossFieldTable, revisionMetadata) {
301
- const rebasedFields = new Map();
302
- // Rebase fields contained in the base changeset
303
- for (const [field, baseChanges] of over) {
304
- const fieldChange = change.get(field) ?? {
305
- fieldKind: genericFieldKind_js_1.genericFieldKind.identifier,
306
- change: (0, index_js_2.brand)((0, genericFieldKind_js_1.newGenericChangeset)()),
428
+ // This performs a first pass on all fields which have both new and base changes.
429
+ // TODO: Can we also handle additional passes in this method?
430
+ rebaseIntersectingFields(crossFieldTable, rebasedNodes, genId, constraintState, metadata) {
431
+ const change = crossFieldTable.newChange;
432
+ const baseChange = crossFieldTable.baseChange;
433
+ const rebasedFields = this.rebaseFieldMap(change.fieldChanges, baseChange.fieldChanges, undefined, genId, crossFieldTable, metadata);
434
+ // This loop processes all fields which have both base and new changes.
435
+ // Note that the call to `rebaseNodeChange` can add entries to `crossFieldTable.nodeIdPairs`.
436
+ for (const [newId, baseId, _attachState] of crossFieldTable.nodeIdPairs) {
437
+ const rebasedNode = this.rebaseNodeChange(newId, baseId, genId, crossFieldTable, metadata, constraintState);
438
+ (0, index_js_1.setInChangeAtomIdMap)(rebasedNodes, newId, rebasedNode);
439
+ }
440
+ return rebasedFields;
441
+ }
442
+ // This processes fields which have no new changes but have been invalidated by another field.
443
+ rebaseFieldsWithoutNewChanges(rebasedFields, rebasedNodes, crossFieldTable, genId, metadata) {
444
+ const baseChange = crossFieldTable.baseChange;
445
+ for (const [revision, localId, fieldKey] of crossFieldTable.affectedBaseFields.keys()) {
446
+ const baseNodeId = localId !== undefined
447
+ ? normalizeNodeId({ revision, localId }, baseChange.nodeAliases)
448
+ : undefined;
449
+ const baseFieldChange = fieldMapFromNodeId(baseChange.fieldChanges, baseChange.nodeChanges, baseNodeId).get(fieldKey);
450
+ (0, internal_1.assert)(baseFieldChange !== undefined, 0x9c2 /* Cross field key registered for empty field */);
451
+ if (crossFieldTable.baseFieldToContext.has(baseFieldChange)) {
452
+ // This field has already been processed because there were changes to rebase.
453
+ continue;
454
+ }
455
+ // This field has no changes in the new changeset, otherwise it would have been added to
456
+ // `crossFieldTable.baseFieldToContext` when processing fields with both base and new changes.
457
+ const rebaseChild = (child, baseChild, stateChange) => {
458
+ (0, internal_1.assert)(child === undefined, 0x9c3 /* There should be no new changes in this field */);
459
+ return undefined;
307
460
  };
308
- const { fieldKind, change1: fieldChangeset, change2: baseChangeset, } = this.normalizeFieldChanges(fieldChange, baseChanges, genId, revisionMetadata);
309
- const manager = newCrossFieldManager(crossFieldTable, fieldChange);
310
- const rebaseChild = (child, baseChild, _attachState) => {
311
- crossFieldTable.nodeIdPairs.push([child, baseChild]);
312
- return (child ??
313
- // The fact `child` is undefined means that the changeset to rebase does not include changes for
314
- // this node or its descendants. However, it's possible that it will after rebasing.
315
- // In that case, we will need a NodeId to represent these changes under in the rebased changeset.
316
- // We adopt `baseChild` for this purpose.
317
- baseChild ??
318
- (0, index_js_2.fail)("Should not have two undefined node IDs"));
461
+ const handler = getChangeHandler(this.fieldKinds, baseFieldChange.fieldKind);
462
+ const fieldChange = {
463
+ ...baseFieldChange,
464
+ change: (0, index_js_2.brand)(handler.createEmpty()),
319
465
  };
320
- const rebasedField = fieldKind.changeHandler.rebaser.rebase(fieldChangeset, baseChangeset, rebaseChild, genId, manager, revisionMetadata);
466
+ const rebasedNodeId = baseNodeId !== undefined
467
+ ? rebasedNodeIdFromBaseNodeId(crossFieldTable, baseNodeId)
468
+ : undefined;
469
+ const fieldId = { nodeId: rebasedNodeId, field: fieldKey };
470
+ const rebasedField = handler.rebaser.rebase(fieldChange.change, baseFieldChange.change, rebaseChild, genId, new RebaseManager(crossFieldTable, baseFieldChange, fieldId), metadata);
321
471
  const rebasedFieldChange = {
322
- fieldKind: fieldKind.identifier,
472
+ ...baseFieldChange,
323
473
  change: (0, index_js_2.brand)(rebasedField),
324
474
  };
325
- rebasedFields.set(field, rebasedFieldChange);
326
- crossFieldTable.fieldToContext.set(fieldChange, {
327
- baseChange: baseChanges,
475
+ // TODO: Deduplicate
476
+ crossFieldTable.baseFieldToContext.set(baseFieldChange, {
328
477
  newChange: fieldChange,
478
+ baseChange: baseFieldChange,
329
479
  rebasedChange: rebasedFieldChange,
480
+ fieldId,
481
+ baseNodeIds: [],
330
482
  });
483
+ crossFieldTable.rebasedFields.add(rebasedFieldChange);
484
+ this.attachRebasedField(rebasedFields, rebasedNodes, crossFieldTable, rebasedFieldChange, fieldId, genId, metadata);
485
+ }
486
+ }
487
+ attachRebasedField(rebasedFields, rebasedNodes, table, rebasedField, { nodeId, field: fieldKey }, idAllocator, metadata) {
488
+ if (nodeId === undefined) {
489
+ rebasedFields.set(fieldKey, rebasedField);
490
+ return;
491
+ }
492
+ const rebasedNode = (0, index_js_1.getFromChangeAtomIdMap)(rebasedNodes, nodeId);
493
+ if (rebasedNode !== undefined) {
494
+ if (rebasedNode.fieldChanges === undefined) {
495
+ rebasedNode.fieldChanges = new Map([[fieldKey, rebasedField]]);
496
+ return;
497
+ }
498
+ (0, internal_1.assert)(!rebasedNode.fieldChanges.has(fieldKey), 0x9c4 /* Expected an empty field */);
499
+ rebasedNode.fieldChanges.set(fieldKey, rebasedField);
500
+ return;
331
501
  }
332
- // Rebase the fields of the new changeset which don't have a corresponding base field.
502
+ const newNode = {
503
+ fieldChanges: new Map([[fieldKey, rebasedField]]),
504
+ };
505
+ (0, index_js_1.setInChangeAtomIdMap)(rebasedNodes, nodeId, newNode);
506
+ (0, index_js_1.setInChangeAtomIdMap)(table.baseToRebasedNodeId, nodeId, nodeId);
507
+ const parentFieldId = getParentFieldId(table.baseChange, nodeId);
508
+ this.attachRebasedNode(rebasedFields, rebasedNodes, table, nodeId, parentFieldId, idAllocator, metadata);
509
+ }
510
+ attachRebasedNode(rebasedFields, rebasedNodes, table, baseNodeId, parentFieldIdBase, idAllocator, metadata) {
511
+ const baseFieldChange = fieldChangeFromId(table.baseChange.fieldChanges, table.baseChange.nodeChanges, parentFieldIdBase);
512
+ const rebasedFieldId = rebasedFieldIdFromBaseId(table, parentFieldIdBase);
513
+ (0, index_js_1.setInChangeAtomIdMap)(table.rebasedNodeToParent, baseNodeId, rebasedFieldId);
514
+ const context = table.baseFieldToContext.get(baseFieldChange);
515
+ if (context !== undefined) {
516
+ // We've already processed this field.
517
+ // The new child node can be attached when processing invalidated fields.
518
+ context.baseNodeIds.push(baseNodeId);
519
+ table.invalidatedFields.add(baseFieldChange);
520
+ return;
521
+ }
522
+ const handler = getChangeHandler(this.fieldKinds, baseFieldChange.fieldKind);
523
+ const fieldChange = {
524
+ ...baseFieldChange,
525
+ change: (0, index_js_2.brand)(handler.createEmpty()),
526
+ };
527
+ const rebasedChangeset = handler.rebaser.rebase(handler.createEmpty(), baseFieldChange.change, (_idNew, idBase) => idBase !== undefined && (0, index_js_1.areEqualChangeAtomIds)(idBase, baseNodeId)
528
+ ? baseNodeId
529
+ : undefined, idAllocator, new RebaseManager(table, baseFieldChange, rebasedFieldId), metadata);
530
+ const rebasedField = { ...baseFieldChange, change: (0, index_js_2.brand)(rebasedChangeset) };
531
+ table.rebasedFields.add(rebasedField);
532
+ table.baseFieldToContext.set(baseFieldChange, {
533
+ newChange: fieldChange,
534
+ baseChange: baseFieldChange,
535
+ rebasedChange: rebasedField,
536
+ fieldId: rebasedFieldId,
537
+ baseNodeIds: [],
538
+ });
539
+ this.attachRebasedField(rebasedFields, rebasedNodes, table, rebasedField, rebasedFieldId, idAllocator, metadata);
540
+ }
541
+ rebaseFieldMap(change, over, parentId, genId, crossFieldTable, revisionMetadata) {
542
+ const rebasedFields = new Map();
543
+ const rebaseChild = (child, baseChild, stateChange) => {
544
+ if (child !== undefined && baseChild !== undefined) {
545
+ crossFieldTable.nodeIdPairs.push([child, baseChild, stateChange]);
546
+ }
547
+ return child;
548
+ };
333
549
  for (const [field, fieldChange] of change) {
334
- if (!over?.has(field)) {
335
- const baseChanges = {
336
- fieldKind: genericFieldKind_js_1.genericFieldKind.identifier,
337
- change: (0, index_js_2.brand)((0, genericFieldKind_js_1.newGenericChangeset)()),
338
- };
339
- const { fieldKind, change1: fieldChangeset, change2: baseChangeset, } = this.normalizeFieldChanges(fieldChange, baseChanges, genId, revisionMetadata);
340
- // TODO: Don't we need to add an entry in the context table?
341
- const manager = newCrossFieldManager(crossFieldTable, fieldChange);
342
- const rebasedChangeset = fieldKind.changeHandler.rebaser.rebase(fieldChangeset, baseChangeset, (child, baseChild) => {
343
- (0, internal_1.assert)(baseChild === undefined, 0x5b6 /* This field should not have any base changes */);
344
- crossFieldTable.nodeIdPairs.push([child, undefined]);
345
- return child;
346
- }, genId, manager, revisionMetadata);
347
- const rebasedFieldChange = {
348
- fieldKind: fieldKind.identifier,
349
- change: (0, index_js_2.brand)(rebasedChangeset),
350
- };
351
- rebasedFields.set(field, rebasedFieldChange);
550
+ const fieldId = { nodeId: parentId, field };
551
+ const baseChange = over.get(field);
552
+ if (baseChange === undefined) {
553
+ rebasedFields.set(field, fieldChange);
554
+ continue;
352
555
  }
556
+ const { fieldKind, changeHandler, change1: fieldChangeset, change2: baseChangeset, } = this.normalizeFieldChanges(fieldChange, baseChange, genId, revisionMetadata);
557
+ const manager = new RebaseManager(crossFieldTable, baseChange, fieldId);
558
+ const rebasedField = changeHandler.rebaser.rebase(fieldChangeset, baseChangeset, rebaseChild, genId, manager, revisionMetadata);
559
+ const rebasedFieldChange = {
560
+ fieldKind,
561
+ change: (0, index_js_2.brand)(rebasedField),
562
+ };
563
+ rebasedFields.set(field, rebasedFieldChange);
564
+ crossFieldTable.baseFieldToContext.set(baseChange, {
565
+ baseChange,
566
+ newChange: fieldChange,
567
+ rebasedChange: rebasedFieldChange,
568
+ fieldId,
569
+ baseNodeIds: [],
570
+ });
571
+ crossFieldTable.rebasedFields.add(rebasedFieldChange);
353
572
  }
354
573
  return rebasedFields;
355
574
  }
356
- rebaseNodeChange(change, over, genId, crossFieldTable, revisionMetadata) {
357
- const key = change ?? over;
358
- if (key === undefined) {
359
- return undefined;
360
- }
575
+ rebaseNodeChange(newId, baseId, genId, crossFieldTable, revisionMetadata, constraintState) {
576
+ const change = nodeChangeFromId(crossFieldTable.newChange.nodeChanges, newId);
577
+ const over = nodeChangeFromId(crossFieldTable.baseChange.nodeChanges, baseId);
361
578
  const baseMap = over?.fieldChanges ?? new Map();
362
- const fieldChanges = this.rebaseFieldMap(change?.fieldChanges ?? new Map(), baseMap, genId, crossFieldTable, revisionMetadata);
579
+ const fieldChanges = change.fieldChanges !== undefined && over.fieldChanges !== undefined
580
+ ? this.rebaseFieldMap(change?.fieldChanges ?? new Map(), baseMap, newId, genId, crossFieldTable, revisionMetadata)
581
+ : change.fieldChanges;
363
582
  const rebasedChange = {};
364
- if (fieldChanges.size > 0) {
583
+ if (fieldChanges !== undefined && fieldChanges.size > 0) {
365
584
  rebasedChange.fieldChanges = fieldChanges;
366
585
  }
367
586
  if (change?.nodeExistsConstraint !== undefined) {
368
587
  rebasedChange.nodeExistsConstraint = change.nodeExistsConstraint;
369
588
  }
370
- crossFieldTable.rebasedNodeCache.set(key, rebasedChange);
589
+ (0, index_js_1.setInChangeAtomIdMap)(crossFieldTable.baseToRebasedNodeId, baseId, newId);
371
590
  return rebasedChange;
372
591
  }
373
592
  updateConstraintsForFields(fields, parentAttachState, constraintState, nodes) {
@@ -399,6 +618,9 @@ class ModularChangeFamily {
399
618
  }
400
619
  }
401
620
  pruneFieldMap(changeset, nodeMap) {
621
+ if (changeset === undefined) {
622
+ return undefined;
623
+ }
402
624
  const prunedChangeset = new Map();
403
625
  for (const [field, fieldChange] of changeset) {
404
626
  const handler = getChangeHandler(this.fieldKinds, fieldChange.fieldKind);
@@ -410,8 +632,7 @@ class ModularChangeFamily {
410
632
  return prunedChangeset.size > 0 ? prunedChangeset : undefined;
411
633
  }
412
634
  pruneNodeChange(nodeId, nodeMap) {
413
- const changeset = (0, index_js_2.tryGetFromNestedMap)(nodeMap, nodeId.revision, nodeId.localId);
414
- (0, internal_1.assert)(changeset !== undefined, 0x930 /* Unknown node ID */);
635
+ const changeset = nodeChangeFromId(nodeMap, nodeId);
415
636
  const prunedFields = changeset.fieldChanges !== undefined
416
637
  ? this.pruneFieldMap(changeset.fieldChanges, nodeMap)
417
638
  : undefined;
@@ -424,7 +645,7 @@ class ModularChangeFamily {
424
645
  return undefined;
425
646
  }
426
647
  else {
427
- (0, index_js_2.setInNestedMap)(nodeMap, nodeId.revision, nodeId.localId, prunedChange);
648
+ (0, index_js_1.setInChangeAtomIdMap)(nodeMap, nodeId, prunedChange);
428
649
  return nodeId;
429
650
  }
430
651
  }
@@ -438,10 +659,19 @@ class ModularChangeFamily {
438
659
  id,
439
660
  this.replaceNodeChangesetRevisions(nodeChangeset, oldRevisions, newRevision),
440
661
  ]));
662
+ const updatedNodeToParent = (0, index_js_2.nestedMapFromFlatList)((0, index_js_2.nestedMapToFlatList)(change.nodeToParent).map(([revision, id, fieldId]) => [
663
+ replaceRevision(revision, oldRevisions, newRevision),
664
+ id,
665
+ replaceFieldIdRevision(normalizeFieldId(fieldId, change.nodeAliases), oldRevisions, newRevision),
666
+ ]));
441
667
  const updated = {
442
668
  ...change,
443
669
  fieldChanges: updatedFields,
444
670
  nodeChanges: updatedNodes,
671
+ nodeToParent: updatedNodeToParent,
672
+ // We've updated all references to old node IDs, so we no longer need an alias table.
673
+ nodeAliases: new Map(),
674
+ crossFieldKeys: replaceCrossFieldKeyTableRevisions(change.crossFieldKeys, oldRevisions, newRevision, change.nodeAliases),
445
675
  };
446
676
  if (change.builds !== undefined) {
447
677
  updated.builds = replaceIdMapRevisions(change.builds, oldRevisions, newRevision);
@@ -474,17 +704,63 @@ class ModularChangeFamily {
474
704
  replaceFieldMapRevisions(fields, oldRevisions, newRevision) {
475
705
  const updatedFields = new Map();
476
706
  for (const [field, fieldChange] of fields) {
477
- const updatedFieldChange = getFieldKind(this.fieldKinds, fieldChange.fieldKind).changeHandler.rebaser.replaceRevisions(fieldChange.change, oldRevisions, newRevision);
478
- updatedFields.set(field, { ...fieldChange, change: updatedFieldChange });
707
+ const updatedFieldChange = getChangeHandler(this.fieldKinds, fieldChange.fieldKind).rebaser.replaceRevisions(fieldChange.change, oldRevisions, newRevision);
708
+ updatedFields.set(field, { ...fieldChange, change: (0, index_js_2.brand)(updatedFieldChange) });
479
709
  }
480
710
  return updatedFields;
481
711
  }
712
+ makeCrossFieldKeyTable(fields, nodes) {
713
+ const keys = newCrossFieldKeyTable();
714
+ this.populateCrossFieldKeyTableForFieldMap(keys, fields, undefined);
715
+ (0, index_js_2.forEachInNestedMap)(nodes, (node, revision, localId) => {
716
+ if (node.fieldChanges !== undefined) {
717
+ this.populateCrossFieldKeyTableForFieldMap(keys, node.fieldChanges, {
718
+ revision,
719
+ localId,
720
+ });
721
+ }
722
+ });
723
+ return keys;
724
+ }
725
+ populateCrossFieldKeyTableForFieldMap(table, fields, parent) {
726
+ for (const [fieldKey, fieldChange] of fields) {
727
+ const keys = getChangeHandler(this.fieldKinds, fieldChange.fieldKind).getCrossFieldKeys(fieldChange.change);
728
+ for (const key of keys) {
729
+ table.set(key, { nodeId: parent, field: fieldKey });
730
+ }
731
+ }
732
+ }
482
733
  buildEditor(changeReceiver) {
483
- return new ModularEditBuilder(this, changeReceiver);
734
+ return new ModularEditBuilder(this, this.fieldKinds, changeReceiver);
735
+ }
736
+ createEmptyFieldChange(fieldKind) {
737
+ const emptyChange = getChangeHandler(this.fieldKinds, fieldKind).createEmpty();
738
+ return { fieldKind, change: (0, index_js_2.brand)(emptyChange) };
484
739
  }
485
740
  }
486
741
  exports.ModularChangeFamily = ModularChangeFamily;
487
742
  ModularChangeFamily.emptyChange = makeModularChangeset();
743
+ function replaceCrossFieldKeyTableRevisions(table, oldRevisions, newRevision, nodeAliases) {
744
+ const updated = newBTree();
745
+ table.forEachPair(([target, revision, id, count], field) => {
746
+ const updatedKey = [
747
+ target,
748
+ replaceRevision(revision, oldRevisions, newRevision),
749
+ id,
750
+ count,
751
+ ];
752
+ const normalizedFieldId = normalizeFieldId(field, nodeAliases);
753
+ const updatedNodeId = normalizedFieldId.nodeId !== undefined
754
+ ? (0, index_js_1.replaceAtomRevisions)(normalizedFieldId.nodeId, oldRevisions, newRevision)
755
+ : undefined;
756
+ const updatedValue = {
757
+ ...normalizedFieldId,
758
+ nodeId: updatedNodeId,
759
+ };
760
+ updated.set(updatedKey, updatedValue);
761
+ });
762
+ return updated;
763
+ }
488
764
  function replaceRevision(revision, oldRevisions, newRevision) {
489
765
  return oldRevisions.has(revision) ? newRevision : revision;
490
766
  }
@@ -600,8 +876,7 @@ function* relevantRemovedRootsFromFields(change, nodeChanges, fieldKinds) {
600
876
  for (const [_, fieldChange] of change) {
601
877
  const handler = getChangeHandler(fieldKinds, fieldChange.fieldKind);
602
878
  const delegate = function* (node) {
603
- const nodeChangeset = (0, index_js_2.tryGetFromNestedMap)(nodeChanges, node.revision, node.localId);
604
- (0, internal_1.assert)(nodeChangeset !== undefined, 0x931 /* Unknown node ID */);
879
+ const nodeChangeset = nodeChangeFromId(nodeChanges, node);
605
880
  if (nodeChangeset.fieldChanges !== undefined) {
606
881
  yield* relevantRemovedRootsFromFields(nodeChangeset.fieldChanges, nodeChanges, fieldKinds);
607
882
  }
@@ -655,7 +930,7 @@ function updateRefreshers(change, getDetachedNode, removedRoots, requireRefreshe
655
930
  }
656
931
  }
657
932
  const { fieldChanges, nodeChanges, maxId, revisions, constraintViolationCount, builds, destroys, } = change;
658
- return makeModularChangeset(fieldChanges, nodeChanges, maxId, revisions, constraintViolationCount, builds, destroys, refreshers);
933
+ return makeModularChangeset(fieldChanges, nodeChanges, change.nodeToParent, change.nodeAliases, change.crossFieldKeys, maxId, revisions, constraintViolationCount, builds, destroys, refreshers);
659
934
  }
660
935
  exports.updateRefreshers = updateRefreshers;
661
936
  /**
@@ -713,8 +988,7 @@ function intoDeltaImpl(change, nodeChanges, idAllocator, fieldKinds) {
713
988
  const delta = new Map();
714
989
  for (const [field, fieldChange] of change) {
715
990
  const deltaField = getChangeHandler(fieldKinds, fieldChange.fieldKind).intoDelta(fieldChange.change, (childChange) => {
716
- const nodeChange = (0, index_js_2.tryGetFromNestedMap)(nodeChanges, childChange.revision, childChange.localId);
717
- (0, internal_1.assert)(nodeChange !== undefined, 0x932 /* Unknown node ID */);
991
+ const nodeChange = nodeChangeFromId(nodeChanges, childChange);
718
992
  return deltaFromNodeChange(nodeChange, nodeChanges, idAllocator, fieldKinds);
719
993
  }, idAllocator);
720
994
  if (!(0, index_js_1.isEmptyFieldChanges)(deltaField)) {
@@ -774,12 +1048,20 @@ function getChangeHandler(fieldKinds, kind) {
774
1048
  return getFieldKind(fieldKinds, kind).changeHandler;
775
1049
  }
776
1050
  exports.getChangeHandler = getChangeHandler;
777
- function newComposeTable() {
1051
+ function newComposeTable(baseChange, newChange) {
778
1052
  return {
779
1053
  ...newCrossFieldTable(),
1054
+ baseChange,
1055
+ newChange,
780
1056
  fieldToContext: new Map(),
781
- nodeIds: new Map(),
782
- nodeIdPairs: [],
1057
+ newFieldToBaseField: new Map(),
1058
+ newToBaseNodeId: new Map(),
1059
+ composedNodes: new Set(),
1060
+ pendingCompositions: {
1061
+ nodeIdsToCompose: [],
1062
+ affectedBaseFields: newBTree(),
1063
+ affectedNewFields: newBTree(),
1064
+ },
783
1065
  };
784
1066
  }
785
1067
  function newCrossFieldTable() {
@@ -796,43 +1078,148 @@ function newConstraintState(violationCount) {
796
1078
  violationCount,
797
1079
  };
798
1080
  }
799
- function newCrossFieldManager(crossFieldTable, currentFieldKey, allowInval = true) {
800
- const getMap = (target) => target === crossFieldQueries_js_1.CrossFieldTarget.Source ? crossFieldTable.srcTable : crossFieldTable.dstTable;
801
- const getDependents = (target) => target === crossFieldQueries_js_1.CrossFieldTarget.Source
802
- ? crossFieldTable.srcDependents
803
- : crossFieldTable.dstDependents;
804
- const manager = {
805
- table: crossFieldTable,
806
- set: (target, revision, id, count, newValue, invalidateDependents) => {
807
- if (invalidateDependents && allowInval) {
808
- const lastChangedId = id + count - 1;
809
- let firstId = id;
810
- while (firstId <= lastChangedId) {
811
- const dependentEntry = (0, crossFieldQueries_js_1.getFirstFromCrossFieldMap)(getDependents(target), revision, firstId, lastChangedId - firstId + 1);
812
- if (dependentEntry.value !== undefined) {
813
- crossFieldTable.invalidatedFields.add(dependentEntry.value);
814
- }
815
- firstId = (0, index_js_2.brand)(firstId + dependentEntry.length);
1081
+ class CrossFieldManagerI {
1082
+ constructor(crossFieldTable, currentFieldKey, allowInval = true) {
1083
+ this.crossFieldTable = crossFieldTable;
1084
+ this.currentFieldKey = currentFieldKey;
1085
+ this.allowInval = allowInval;
1086
+ }
1087
+ set(target, revision, id, count, newValue, invalidateDependents) {
1088
+ if (invalidateDependents && this.allowInval) {
1089
+ const lastChangedId = id + count - 1;
1090
+ let firstId = id;
1091
+ while (firstId <= lastChangedId) {
1092
+ const dependentEntry = (0, crossFieldQueries_js_1.getFirstFromCrossFieldMap)(this.getDependents(target), revision, firstId, lastChangedId - firstId + 1);
1093
+ if (dependentEntry.value !== undefined) {
1094
+ this.crossFieldTable.invalidatedFields.add(dependentEntry.value);
816
1095
  }
1096
+ firstId = (0, index_js_2.brand)(firstId + dependentEntry.length);
817
1097
  }
818
- (0, crossFieldQueries_js_1.setInCrossFieldMap)(getMap(target), revision, id, count, newValue);
819
- },
820
- get: (target, revision, id, count, addDependency) => {
821
- if (addDependency) {
822
- // We assume that if there is already an entry for this ID it is because
823
- // a field handler has called compose on the same node multiple times.
824
- // In this case we only want to update the latest version, so we overwrite the dependency.
825
- (0, crossFieldQueries_js_1.setInCrossFieldMap)(getDependents(target), revision, id, count, currentFieldKey);
1098
+ }
1099
+ (0, crossFieldQueries_js_1.setInCrossFieldMap)(this.getMap(target), revision, id, count, newValue);
1100
+ }
1101
+ get(target, revision, id, count, addDependency) {
1102
+ if (addDependency) {
1103
+ // We assume that if there is already an entry for this ID it is because
1104
+ // a field handler has called compose on the same node multiple times.
1105
+ // In this case we only want to update the latest version, so we overwrite the dependency.
1106
+ (0, crossFieldQueries_js_1.setInCrossFieldMap)(this.getDependents(target), revision, id, count, this.currentFieldKey);
1107
+ }
1108
+ return (0, crossFieldQueries_js_1.getFirstFromCrossFieldMap)(this.getMap(target), revision, id, count);
1109
+ }
1110
+ getMap(target) {
1111
+ return target === crossFieldQueries_js_1.CrossFieldTarget.Source
1112
+ ? this.crossFieldTable.srcTable
1113
+ : this.crossFieldTable.dstTable;
1114
+ }
1115
+ getDependents(target) {
1116
+ return target === crossFieldQueries_js_1.CrossFieldTarget.Source
1117
+ ? this.crossFieldTable.srcDependents
1118
+ : this.crossFieldTable.dstDependents;
1119
+ }
1120
+ }
1121
+ class InvertManager extends CrossFieldManagerI {
1122
+ constructor(table, field, fieldId, allowInval = true) {
1123
+ super(table, field, allowInval);
1124
+ this.fieldId = fieldId;
1125
+ }
1126
+ onMoveIn(id) {
1127
+ (0, index_js_1.setInChangeAtomIdMap)(this.table.invertedNodeToParent, id, this.fieldId);
1128
+ }
1129
+ moveKey(target, revision, id, count) {
1130
+ (0, internal_1.assert)(false, 0x9c5 /* Keys should not be moved manually during invert */);
1131
+ }
1132
+ get table() {
1133
+ return this.crossFieldTable;
1134
+ }
1135
+ }
1136
+ class RebaseManager extends CrossFieldManagerI {
1137
+ constructor(table, currentField, fieldId, allowInval = true) {
1138
+ super(table, currentField, allowInval);
1139
+ this.fieldId = fieldId;
1140
+ }
1141
+ set(target, revision, id, count, newValue, invalidateDependents) {
1142
+ if (invalidateDependents && this.allowInval) {
1143
+ const newFieldIds = getFieldsForCrossFieldKey(this.table.newChange, [
1144
+ target,
1145
+ revision,
1146
+ id,
1147
+ count,
1148
+ ]);
1149
+ (0, internal_1.assert)(newFieldIds.length === 0, 0x9c6 /* TODO: Modifying a cross-field key from the new changeset is currently unsupported */);
1150
+ const baseFieldIds = getFieldsForCrossFieldKey(this.table.baseChange, [
1151
+ target,
1152
+ revision,
1153
+ id,
1154
+ count,
1155
+ ]);
1156
+ (0, internal_1.assert)(baseFieldIds.length > 0, 0x9c7 /* Cross field key not registered in base or new change */);
1157
+ for (const baseFieldId of baseFieldIds) {
1158
+ this.table.affectedBaseFields.set([baseFieldId.nodeId?.revision, baseFieldId.nodeId?.localId, baseFieldId.field], true);
826
1159
  }
827
- return (0, crossFieldQueries_js_1.getFirstFromCrossFieldMap)(getMap(target), revision, id, count);
828
- },
829
- };
830
- return manager;
1160
+ }
1161
+ super.set(target, revision, id, count, newValue, invalidateDependents);
1162
+ }
1163
+ onMoveIn(id) {
1164
+ (0, index_js_1.setInChangeAtomIdMap)(this.table.rebasedNodeToParent, id, this.fieldId);
1165
+ }
1166
+ moveKey(target, revision, id, count) {
1167
+ setInCrossFieldKeyTable(this.table.rebasedCrossFieldKeys, target, revision, id, count, this.fieldId);
1168
+ }
1169
+ get table() {
1170
+ return this.crossFieldTable;
1171
+ }
1172
+ }
1173
+ // TODO: Deduplicate this with RebaseTable
1174
+ class ComposeManager extends CrossFieldManagerI {
1175
+ constructor(table, currentField, allowInval = true) {
1176
+ super(table, currentField, allowInval);
1177
+ }
1178
+ set(target, revision, id, count, newValue, invalidateDependents) {
1179
+ if (invalidateDependents && this.allowInval) {
1180
+ const newFieldIds = getFieldsForCrossFieldKey(this.table.newChange, [
1181
+ target,
1182
+ revision,
1183
+ id,
1184
+ count,
1185
+ ]);
1186
+ if (newFieldIds.length > 0) {
1187
+ for (const newFieldId of newFieldIds) {
1188
+ this.table.pendingCompositions.affectedNewFields.set([newFieldId.nodeId?.revision, newFieldId.nodeId?.localId, newFieldId.field], true);
1189
+ }
1190
+ }
1191
+ else {
1192
+ const baseFieldIds = getFieldsForCrossFieldKey(this.table.baseChange, [
1193
+ target,
1194
+ revision,
1195
+ id,
1196
+ count,
1197
+ ]);
1198
+ (0, internal_1.assert)(baseFieldIds.length > 0, 0x9c8 /* Cross field key not registered in base or new change */);
1199
+ for (const baseFieldId of baseFieldIds) {
1200
+ this.table.pendingCompositions.affectedBaseFields.set([baseFieldId.nodeId?.revision, baseFieldId.nodeId?.localId, baseFieldId.field], true);
1201
+ }
1202
+ }
1203
+ }
1204
+ super.set(target, revision, id, count, newValue, invalidateDependents);
1205
+ }
1206
+ onMoveIn(id) {
1207
+ throw new Error("Method not implemented.");
1208
+ }
1209
+ moveKey(target, revision, id, count) {
1210
+ throw new Error("Method not implemented.");
1211
+ }
1212
+ get table() {
1213
+ return this.crossFieldTable;
1214
+ }
831
1215
  }
832
- function makeModularChangeset(fieldChanges = undefined, nodeChanges = undefined, maxId = -1, revisions = undefined, constraintViolationCount = undefined, builds, destroys, refreshers) {
1216
+ function makeModularChangeset(fieldChanges = undefined, nodeChanges = undefined, nodeToParent = undefined, nodeAliases = undefined, crossFieldKeys = undefined, maxId = -1, revisions = undefined, constraintViolationCount = undefined, builds, destroys, refreshers) {
833
1217
  const changeset = {
834
1218
  fieldChanges: fieldChanges ?? new Map(),
835
1219
  nodeChanges: nodeChanges ?? new Map(),
1220
+ nodeToParent: nodeToParent ?? new Map(),
1221
+ nodeAliases: nodeAliases ?? new Map(),
1222
+ crossFieldKeys: crossFieldKeys ?? newCrossFieldKeyTable(),
836
1223
  };
837
1224
  if (revisions !== undefined && revisions.length > 0) {
838
1225
  changeset.revisions = revisions;
@@ -855,8 +1242,9 @@ function makeModularChangeset(fieldChanges = undefined, nodeChanges = undefined,
855
1242
  return changeset;
856
1243
  }
857
1244
  class ModularEditBuilder extends index_js_1.EditBuilder {
858
- constructor(family, changeReceiver) {
1245
+ constructor(family, fieldKinds, changeReceiver) {
859
1246
  super(family, changeReceiver);
1247
+ this.fieldKinds = fieldKinds;
860
1248
  this.transactionDepth = 0;
861
1249
  this.idAllocator = (0, index_js_2.idAllocatorFromMaxId)();
862
1250
  }
@@ -902,7 +1290,8 @@ class ModularEditBuilder extends index_js_1.EditBuilder {
902
1290
  * @param maxId - the highest `ChangesetLocalId` used in this change
903
1291
  */
904
1292
  submitChange(field, fieldKind, change) {
905
- const modularChange = buildModularChangesetFromField(field, { fieldKind, change }, new Map(), this.idAllocator);
1293
+ const crossFieldKeys = getChangeHandler(this.fieldKinds, fieldKind).getCrossFieldKeys(change);
1294
+ const modularChange = buildModularChangesetFromField(field, { fieldKind, change }, new Map(), new Map(), newCrossFieldKeyTable(), this.idAllocator, crossFieldKeys);
906
1295
  this.applyChange(modularChange);
907
1296
  }
908
1297
  submitChanges(changes) {
@@ -911,11 +1300,11 @@ class ModularEditBuilder extends index_js_1.EditBuilder {
911
1300
  }
912
1301
  buildChanges(changes) {
913
1302
  const changeMaps = changes.map((change) => (0, index_js_1.makeAnonChange)(change.type === "global"
914
- ? makeModularChangeset(undefined, undefined, this.idAllocator.getMaxId(), undefined, undefined, change.builds)
1303
+ ? makeModularChangeset(undefined, undefined, undefined, undefined, undefined, this.idAllocator.getMaxId(), undefined, undefined, change.builds)
915
1304
  : buildModularChangesetFromField(change.field, {
916
1305
  fieldKind: change.fieldKind,
917
1306
  change: change.change,
918
- }, new Map(), this.idAllocator)));
1307
+ }, new Map(), new Map(), newCrossFieldKeyTable(), this.idAllocator, getChangeHandler(this.fieldKinds, change.fieldKind).getCrossFieldKeys(change.change))));
919
1308
  const composedChange = this.changeFamily.rebaser.compose(changeMaps);
920
1309
  const maxId = (0, index_js_2.brand)(this.idAllocator.getMaxId());
921
1310
  if (maxId >= 0) {
@@ -930,29 +1319,47 @@ class ModularEditBuilder extends index_js_1.EditBuilder {
930
1319
  const nodeChange = {
931
1320
  nodeExistsConstraint: { violated: false },
932
1321
  };
933
- this.applyChange(buildModularChangesetFromNode(path, nodeChange, new Map(), this.idAllocator));
1322
+ this.applyChange(buildModularChangesetFromNode(path, nodeChange, new Map(), new Map(), newCrossFieldKeyTable(), this.idAllocator));
934
1323
  }
935
1324
  }
936
1325
  exports.ModularEditBuilder = ModularEditBuilder;
937
- function buildModularChangesetFromField(path, fieldChange, nodeChanges, idAllocator = (0, index_js_2.idAllocatorFromMaxId)()) {
1326
+ function buildModularChangesetFromField(path, fieldChange, nodeChanges, nodeToParent, crossFieldKeys, idAllocator = (0, index_js_2.idAllocatorFromMaxId)(), localCrossFieldKeys = [], childId = undefined) {
938
1327
  const fieldChanges = new Map([[path.field, fieldChange]]);
939
1328
  if (path.parent === undefined) {
940
- return makeModularChangeset(fieldChanges, nodeChanges, idAllocator.getMaxId());
1329
+ for (const key of localCrossFieldKeys) {
1330
+ crossFieldKeys.set(key, { nodeId: undefined, field: path.field });
1331
+ }
1332
+ if (childId !== undefined) {
1333
+ (0, index_js_1.setInChangeAtomIdMap)(nodeToParent, childId, {
1334
+ nodeId: undefined,
1335
+ field: path.field,
1336
+ });
1337
+ }
1338
+ return makeModularChangeset(fieldChanges, nodeChanges, nodeToParent, undefined, crossFieldKeys, idAllocator.getMaxId());
941
1339
  }
942
1340
  const nodeChangeset = {
943
1341
  fieldChanges,
944
1342
  };
945
- return buildModularChangesetFromNode(path.parent, nodeChangeset, nodeChanges, idAllocator);
1343
+ const parentId = { localId: (0, index_js_2.brand)(idAllocator.allocate()) };
1344
+ for (const key of localCrossFieldKeys) {
1345
+ crossFieldKeys.set(key, { nodeId: parentId, field: path.field });
1346
+ }
1347
+ if (childId !== undefined) {
1348
+ (0, index_js_1.setInChangeAtomIdMap)(nodeToParent, childId, {
1349
+ nodeId: parentId,
1350
+ field: path.field,
1351
+ });
1352
+ }
1353
+ return buildModularChangesetFromNode(path.parent, nodeChangeset, nodeChanges, nodeToParent, crossFieldKeys, idAllocator, parentId);
946
1354
  }
947
- function buildModularChangesetFromNode(path, nodeChange, nodeChanges, idAllocator) {
948
- const nodeId = { localId: (0, index_js_2.brand)(idAllocator.allocate()) };
949
- (0, index_js_2.setInNestedMap)(nodeChanges, nodeId.revision, nodeId.localId, nodeChange);
1355
+ function buildModularChangesetFromNode(path, nodeChange, nodeChanges, nodeToParent, crossFieldKeys, idAllocator, nodeId = { localId: (0, index_js_2.brand)(idAllocator.allocate()) }) {
1356
+ (0, index_js_1.setInChangeAtomIdMap)(nodeChanges, nodeId, nodeChange);
950
1357
  const fieldChangeset = genericFieldKind_js_1.genericFieldKind.changeHandler.editor.buildChildChange(path.parentIndex, nodeId);
951
1358
  const fieldChange = {
952
1359
  fieldKind: genericFieldKind_js_1.genericFieldKind.identifier,
953
1360
  change: fieldChangeset,
954
1361
  };
955
- return buildModularChangesetFromField({ parent: path.parent, field: path.parentField }, fieldChange, nodeChanges, idAllocator);
1362
+ return buildModularChangesetFromField({ parent: path.parent, field: path.parentField }, fieldChange, nodeChanges, nodeToParent, crossFieldKeys, idAllocator, [], nodeId);
956
1363
  }
957
1364
  function getRevInfoFromTaggedChanges(changes) {
958
1365
  let maxId = -1;
@@ -1001,9 +1408,184 @@ function revisionFromRevInfos(revInfos) {
1001
1408
  }
1002
1409
  return revInfos[0].revision;
1003
1410
  }
1004
- function getActiveFieldChanges(changes) {
1005
- return (changes.constraintViolationCount ?? 0) === 0
1006
- ? changes.fieldChanges
1007
- : new Map();
1411
+ function mergeBTrees(tree1, tree2) {
1412
+ const result = tree1.clone();
1413
+ tree2.forEachPair((k, v) => {
1414
+ result.set(k, v);
1415
+ });
1416
+ return result;
1417
+ }
1418
+ function mergeNestedMaps(map1, map2) {
1419
+ const merged = new Map();
1420
+ (0, index_js_2.populateNestedMap)(map1, merged, true);
1421
+ (0, index_js_2.populateNestedMap)(map2, merged, true);
1422
+ return merged;
1423
+ }
1424
+ function fieldChangeFromId(fields, nodes, id) {
1425
+ const fieldMap = fieldMapFromNodeId(fields, nodes, id.nodeId);
1426
+ return fieldMap.get(id.field) ?? (0, index_js_2.fail)("No field exists for the given ID");
1427
+ }
1428
+ function fieldMapFromNodeId(rootFieldMap, nodes, nodeId) {
1429
+ if (nodeId === undefined) {
1430
+ return rootFieldMap;
1431
+ }
1432
+ const node = nodeChangeFromId(nodes, nodeId);
1433
+ (0, internal_1.assert)(node.fieldChanges !== undefined, 0x9c9 /* Expected node to have field changes */);
1434
+ return node.fieldChanges;
1435
+ }
1436
+ function rebasedFieldIdFromBaseId(table, baseId) {
1437
+ if (baseId.nodeId === undefined) {
1438
+ return baseId;
1439
+ }
1440
+ return { ...baseId, nodeId: rebasedNodeIdFromBaseNodeId(table, baseId.nodeId) };
1441
+ }
1442
+ function rebasedNodeIdFromBaseNodeId(table, baseId) {
1443
+ return (0, index_js_1.getFromChangeAtomIdMap)(table.baseToRebasedNodeId, baseId) ?? baseId;
1444
+ }
1445
+ function nodeChangeFromId(nodes, id) {
1446
+ const node = (0, index_js_1.getFromChangeAtomIdMap)(nodes, id);
1447
+ (0, internal_1.assert)(node !== undefined, 0x9ca /* Unknown node ID */);
1448
+ return node;
1449
+ }
1450
+ function fieldIdFromFieldIdKey([revision, localId, field]) {
1451
+ const nodeId = localId !== undefined ? { revision, localId } : undefined;
1452
+ return { nodeId, field };
1453
+ }
1454
+ function cloneNodeChangeset(nodeChangeset) {
1455
+ if (nodeChangeset.fieldChanges !== undefined) {
1456
+ return { ...nodeChangeset, fieldChanges: new Map(nodeChangeset.fieldChanges) };
1457
+ }
1458
+ return { ...nodeChangeset };
1459
+ }
1460
+ function replaceFieldIdRevision(fieldId, oldRevisions, newRevision) {
1461
+ if (fieldId.nodeId === undefined) {
1462
+ return fieldId;
1463
+ }
1464
+ return {
1465
+ ...fieldId,
1466
+ nodeId: (0, index_js_1.replaceAtomRevisions)(fieldId.nodeId, oldRevisions, newRevision),
1467
+ };
1468
+ }
1469
+ function getParentFieldId(changeset, nodeId) {
1470
+ const parentId = (0, index_js_1.getFromChangeAtomIdMap)(changeset.nodeToParent, nodeId);
1471
+ (0, internal_1.assert)(parentId !== undefined, 0x9cb /* Parent field should be defined */);
1472
+ return normalizeFieldId(parentId, changeset.nodeAliases);
1473
+ }
1474
+ exports.getParentFieldId = getParentFieldId;
1475
+ function getFieldsForCrossFieldKey(changeset, [target, revision, id, count]) {
1476
+ let firstLocalId = id;
1477
+ const lastLocalId = id + count - 1;
1478
+ const fields = [];
1479
+ // eslint-disable-next-line no-constant-condition
1480
+ while (true) {
1481
+ const entry = getFirstIntersectingCrossFieldEntry(changeset.crossFieldKeys, [
1482
+ target,
1483
+ revision,
1484
+ (0, index_js_2.brand)(firstLocalId),
1485
+ count,
1486
+ ]);
1487
+ if (entry === undefined) {
1488
+ return fields;
1489
+ }
1490
+ const [[_target, _revision, entryId, entryCount], fieldId] = entry;
1491
+ fields.push(normalizeFieldId(fieldId, changeset.nodeAliases));
1492
+ const entryLastId = entryId + entryCount - 1;
1493
+ if (entryLastId >= lastLocalId) {
1494
+ return fields;
1495
+ }
1496
+ firstLocalId = entryLastId + 1;
1497
+ }
1498
+ }
1499
+ exports.getFieldsForCrossFieldKey = getFieldsForCrossFieldKey;
1500
+ function getFirstIntersectingCrossFieldEntry(table, [target, revision, id, count]) {
1501
+ const entry = table.nextLowerPair([target, revision, id, Infinity]);
1502
+ if (entry === undefined) {
1503
+ return undefined;
1504
+ }
1505
+ const [entryTarget, entryRevision, entryId, entryCount] = entry[0];
1506
+ if (entryTarget !== target || entryRevision !== revision) {
1507
+ return undefined;
1508
+ }
1509
+ const lastQueryId = id + count - 1;
1510
+ const entryLastId = entryId + entryCount - 1;
1511
+ if (entryId > lastQueryId || entryLastId < id) {
1512
+ return undefined;
1513
+ }
1514
+ return entry;
1515
+ }
1516
+ function setInCrossFieldKeyTable(table, target, revision, id, count, value) {
1517
+ let entry = getFirstIntersectingCrossFieldEntry(table, [target, revision, id, count]);
1518
+ const lastQueryId = id + count - 1;
1519
+ while (entry !== undefined) {
1520
+ const [entryKey, entryValue] = entry;
1521
+ table.delete(entryKey);
1522
+ const [_target, _revision, entryId, entryCount] = entryKey;
1523
+ if (entryId < id) {
1524
+ table.set([target, revision, entryId, id - entryId], entryValue);
1525
+ }
1526
+ const lastEntryId = entryId + entryCount - 1;
1527
+ if (lastEntryId > lastQueryId) {
1528
+ table.set([target, revision, (0, index_js_2.brand)(lastQueryId + 1), lastEntryId - lastQueryId], entryValue);
1529
+ break;
1530
+ }
1531
+ const nextId = (0, index_js_2.brand)(lastEntryId + 1);
1532
+ entry = getFirstIntersectingCrossFieldEntry(table, [
1533
+ target,
1534
+ revision,
1535
+ nextId,
1536
+ lastQueryId - nextId + 1,
1537
+ ]);
1538
+ }
1539
+ table.set([target, revision, id, count], value);
1540
+ }
1541
+ function normalizeFieldId(fieldId, nodeAliases) {
1542
+ return fieldId.nodeId !== undefined
1543
+ ? { ...fieldId, nodeId: normalizeNodeId(fieldId.nodeId, nodeAliases) }
1544
+ : fieldId;
1545
+ }
1546
+ /**
1547
+ * @returns The canonical form of nodeId, according to nodeAliases
1548
+ */
1549
+ function normalizeNodeId(nodeId, nodeAliases) {
1550
+ let currentId = nodeId;
1551
+ // eslint-disable-next-line no-constant-condition
1552
+ while (true) {
1553
+ const dealiased = (0, index_js_1.getFromChangeAtomIdMap)(nodeAliases, currentId);
1554
+ if (dealiased === undefined) {
1555
+ return currentId;
1556
+ }
1557
+ currentId = dealiased;
1558
+ }
1559
+ }
1560
+ function hasConflicts(change) {
1561
+ return (change.constraintViolationCount ?? 0) > 0;
1562
+ }
1563
+ function newCrossFieldKeyTable() {
1564
+ return newBTree();
1565
+ }
1566
+ exports.newCrossFieldKeyTable = newCrossFieldKeyTable;
1567
+ function newBTree() {
1568
+ return (0, index_js_2.brand)(new sorted_btree_es6_1.BTree(undefined, compareTuples));
1569
+ }
1570
+ // This assumes that the arrays are the same length.
1571
+ function compareTuples(arrayA, arrayB) {
1572
+ for (let i = 0; i < arrayA.length; i++) {
1573
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1574
+ const a = arrayA[i];
1575
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1576
+ const b = arrayB[i];
1577
+ if (a < b) {
1578
+ return -1;
1579
+ }
1580
+ else if (a > b) {
1581
+ return 1;
1582
+ }
1583
+ }
1584
+ return 0;
1585
+ }
1586
+ function cloneNestedMap(map) {
1587
+ const cloned = new Map();
1588
+ (0, index_js_2.populateNestedMap)(map, cloned, true);
1589
+ return cloned;
1008
1590
  }
1009
1591
  //# sourceMappingURL=modularChangeFamily.js.map