@@ -85,7 +85,7 @@ export class Root {
8585
8686 } else if ( child . parentChain ) {
8787 // re-assigning a child of the same root, move it next to parent
88- this . recursivelyMoveNextToParent ( child ) ;
88+ this . moveNextToParent ( child ) ;
8989 }
9090 }
9191 } ) ;
@@ -135,6 +135,16 @@ export class Root {
135135 const parentNode = parent [ $changes ] [ changeSetName ] ?. queueRootNode ;
136136 if ( ! parentNode || parentNode === node ) return ;
137137
138+ // Use cached positions - no iteration needed!
139+ const parentPosition = parentNode . position ;
140+ const childPosition = node . position ;
141+
142+ // If child is already after parent, no need to move
143+ if ( childPosition > parentPosition ) return ;
144+
145+ // Child is before parent, so we need to move it after parent
146+ // This maintains decoding order (parent before child)
147+
138148 // Remove node from current position
139149 if ( node . prev ) {
140150 node . prev . next = node . next ;
@@ -159,77 +169,10 @@ export class Root {
159169 }
160170
161171 parentNode . next = node ;
162- }
163172
164- // moveSubtreeToEndOfChangeTreeList(changeSetName: ChangeSetName, changeTree: ChangeTree): void {
165- // // Find the contiguous range of nodes that belong to this subtree
166- // const subtreeRange = this.findSubtreeRange(changeTree, changeSetName);
167- // if (!subtreeRange) return;
168-
169- // const changeSet = this[changeSetName];
170- // const { firstNode, lastNode } = subtreeRange;
171-
172- // // If the last node is already at the tail, no need to move
173- // if (lastNode === changeSet.tail) return;
174-
175- // // Remove the entire subtree range from current position
176- // if (firstNode.prev) {
177- // firstNode.prev.next = lastNode.next;
178- // } else {
179- // changeSet.next = lastNode.next;
180- // }
181-
182- // if (lastNode.next) {
183- // lastNode.next.prev = firstNode.prev;
184- // } else {
185- // changeSet.tail = firstNode.prev;
186- // }
187-
188- // // Add the entire subtree to the end
189- // firstNode.prev = changeSet.tail;
190- // lastNode.next = undefined;
191-
192- // if (changeSet.tail) {
193- // changeSet.tail.next = firstNode;
194- // } else {
195- // changeSet.next = firstNode;
196- // }
197-
198- // changeSet.tail = lastNode;
199- // }
200-
201- // private findSubtreeRange(changeTree: ChangeTree, changeSetName: ChangeSetName): { firstNode: ChangeTreeNode, lastNode: ChangeTreeNode } | null {
202- // const rootNode = changeTree[changeSetName].queueRootNode;
203- // if (!rootNode) return null;
204-
205- // // Collect all refIds that belong to this subtree
206- // const subtreeRefIds = new Set<number>();
207- // this.collectSubtreeRefIds(changeTree, subtreeRefIds);
208-
209- // // Find the first and last nodes in the linked list that belong to this subtree
210- // let firstNode: ChangeTreeNode | null = null;
211- // let lastNode: ChangeTreeNode | null = null;
212- // let current = this[changeSetName].next;
213-
214- // while (current) {
215- // if (subtreeRefIds.has(current.changeTree.refId)) {
216- // if (!firstNode) firstNode = current;
217- // lastNode = current;
218- // }
219- // current = current.next;
220- // }
221-
222- // return firstNode && lastNode ? { firstNode, lastNode } : null;
223- // }
224-
225- // private collectSubtreeRefIds(changeTree: ChangeTree, result: Set<number>): void {
226- // result.add(changeTree.refId);
227-
228- // // Collect children recursively
229- // changeTree.forEachChild((child, _) => {
230- // this.collectSubtreeRefIds(child, result);
231- // });
232- // }
173+ // Update positions after the move
174+ this . updatePositionsAfterMove ( changeSet , node , parentPosition + 1 ) ;
175+ }
233176
234177 public enqueueChangeTree (
235178 changeTree : ChangeTree ,
@@ -244,7 +187,12 @@ export class Root {
244187 }
245188
246189 protected addToChangeTreeList ( list : ChangeTreeList , changeTree : ChangeTree ) : ChangeTreeNode {
247- const node : ChangeTreeNode = { changeTree, next : undefined , prev : undefined } ;
190+ const node : ChangeTreeNode = {
191+ changeTree,
192+ next : undefined ,
193+ prev : undefined ,
194+ position : list . tail ? list . tail . position + 1 : 0
195+ } ;
248196
249197 if ( ! list . next ) {
250198 list . next = node ;
@@ -255,16 +203,42 @@ export class Root {
255203 list . tail = node ;
256204 }
257205
258- list . length ++ ;
259-
260206 return node ;
261207 }
262208
209+ protected updatePositionsAfterRemoval ( list : ChangeTreeList , removedPosition : number ) {
210+ // Update positions for all nodes after the removed position
211+ let current = list . next ;
212+ let position = 0 ;
213+
214+ while ( current ) {
215+ if ( position >= removedPosition ) {
216+ current . position = position ;
217+ }
218+ current = current . next ;
219+ position ++ ;
220+ }
221+ }
222+
223+ protected updatePositionsAfterMove ( list : ChangeTreeList , node : ChangeTreeNode , newPosition : number ) {
224+ // Recalculate all positions - this is more reliable than trying to be clever
225+ let current = list . next ;
226+ let position = 0 ;
227+
228+ while ( current ) {
229+ current . position = position ;
230+ current = current . next ;
231+ position ++ ;
232+ }
233+ }
234+
263235 public removeChangeFromChangeSet ( changeSetName : ChangeSetName , changeTree : ChangeTree ) {
264236 const changeSet = this [ changeSetName ] ;
265237 const node = changeTree [ changeSetName ] . queueRootNode ;
266238
267239 if ( node && node . changeTree === changeTree ) {
240+ const removedPosition = node . position ;
241+
268242 // Remove the node from the linked list
269243 if ( node . prev ) {
270244 node . prev . next = node . next ;
@@ -278,7 +252,8 @@ export class Root {
278252 changeSet . tail = node . prev ;
279253 }
280254
281- changeSet . length -- ;
255+ // Update positions for nodes that came after the removed node
256+ this . updatePositionsAfterRemoval ( changeSet , removedPosition ) ;
282257
283258 // Clear ChangeTree reference
284259 changeTree [ changeSetName ] . queueRootNode = undefined ;
0 commit comments