@@ -23,7 +23,6 @@ const Immutable = require('immutable');
2323const invariant = require ( 'invariant' ) ;
2424
2525type SiblingInsertPosition = 'previous' | 'next' ;
26- type ChildInsertPosition = 'first' | 'last' ;
2726
2827const verifyTree = ( tree : BlockMap ) : void => {
2928 if ( __DEV__ ) {
@@ -32,67 +31,62 @@ const verifyTree = (tree: BlockMap): void => {
3231} ;
3332
3433/**
35- * This is a utility method for setting B as a first/last child of A, ensuring
34+ * This is a utility method for setting B as a child of A, ensuring
3635 * that parent <-> child operations are correctly mirrored
3736 *
37+ * The child is inserted at 'position' index in the list
38+ *
3839 * The block map returned by this method may not be a valid tree (siblings are
3940 * unaffected)
4041 */
4142const updateParentChild = (
4243 blockMap : BlockMap ,
4344 parentKey : string ,
4445 childKey : string ,
45- position : ChildInsertPosition ,
46+ position : number ,
4647) : BlockMap => {
4748 const parent = blockMap . get ( parentKey ) ;
4849 const child = blockMap . get ( childKey ) ;
4950 invariant (
5051 parent != null && child != null ,
5152 'parent & child should exist in the block map' ,
5253 ) ;
53- const existingChildren = parent . getChildKeys ( ) ;
5454 const newBlocks = { } ;
55+ const existingChildren = parent . getChildKeys ( ) ;
56+ invariant (
57+ existingChildren != null &&
58+ position >= 0 &&
59+ position <= existingChildren . count ( ) ,
60+ 'position is not valid for the number of children' ,
61+ ) ;
62+
5563 // add as parent's child
5664 newBlocks [ parentKey ] = parent . merge ( {
57- children :
58- position === 'first'
59- ? existingChildren . unshift ( childKey )
60- : existingChildren . push ( childKey ) ,
65+ children : existingChildren . splice ( position , 0 , childKey ) ,
6166 } ) ;
62- // add as child's parent
63- if ( existingChildren . count ( ) !== 0 ) {
64- // link child as sibling to the existing children
65- switch ( position ) {
66- case 'first' :
67- const nextSiblingKey = existingChildren . first ( ) ;
68- newBlocks [ childKey ] = child . merge ( {
69- parent : parentKey ,
70- nextSibling : nextSiblingKey ,
71- prevSibling : null ,
72- } ) ;
73- newBlocks [ nextSiblingKey ] = blockMap . get ( nextSiblingKey ) . merge ( {
74- prevSibling : childKey ,
75- } ) ;
76- break ;
77- case 'last' :
78- const prevSiblingKey = existingChildren . last ( ) ;
79- newBlocks [ childKey ] = child . merge ( {
80- parent : parentKey ,
81- prevSibling : prevSiblingKey ,
82- nextSibling : null ,
83- } ) ;
84- newBlocks [ prevSiblingKey ] = blockMap . get ( prevSiblingKey ) . merge ( {
85- nextSibling : childKey ,
86- } ) ;
87- break ;
88- }
89- } else {
90- newBlocks [ childKey ] = child . merge ( {
91- parent : parentKey ,
92- prevSibling : null ,
93- nextSibling : null ,
67+
68+ let nextSiblingKey = null ;
69+ let prevSiblingKey = null ;
70+ // link new child as next sibling to the correct existing child
71+ if ( position > 0 ) {
72+ prevSiblingKey = existingChildren . get ( position - 1 ) ;
73+ newBlocks [ prevSiblingKey ] = blockMap . get ( prevSiblingKey ) . merge ( {
74+ nextSibling : childKey ,
75+ } ) ;
76+ }
77+ // link new child as previous sibling to the correct existing child
78+ if ( position < existingChildren . count ( ) ) {
79+ nextSiblingKey = existingChildren . get ( position ) ;
80+ newBlocks [ nextSiblingKey ] = blockMap . get ( nextSiblingKey ) . merge ( {
81+ prevSibling : childKey ,
9482 } ) ;
9583 }
84+ // add parent & siblings to the child
85+ newBlocks [ childKey ] = child . merge ( {
86+ parent : parentKey ,
87+ prevSibling : prevSiblingKey ,
88+ nextSibling : nextSiblingKey ,
89+ } ) ;
9690 return blockMap . merge ( newBlocks ) ;
9791} ;
9892
@@ -181,12 +175,7 @@ const createNewParent = (blockMap: BlockMap, key: string): BlockMap => {
181175 . concat ( Immutable . OrderedMap ( [ [ newParent . getKey ( ) , newParent ] ] ) )
182176 . concat ( blockMap . skipUntil ( block => block . getKey ( ) === key ) ) ;
183177 // set parent <-> child connection
184- newBlockMap = updateParentChild (
185- newBlockMap ,
186- newParent . getKey ( ) ,
187- key ,
188- 'first' ,
189- ) ;
178+ newBlockMap = updateParentChild ( newBlockMap , newParent . getKey ( ) , key , 0 ) ;
190179 // set siblings & parent for the new parent key to child's siblings & parent
191180 const prevSibling = block . getPrevSiblingKey ( ) ;
192181 const nextSibling = block . getNextSiblingKey ( ) ;
@@ -239,7 +228,7 @@ const updateAsSiblingsChild = (
239228 let newBlockMap = blockMap ;
240229 switch ( position ) {
241230 case 'next' :
242- newBlockMap = updateParentChild ( newBlockMap , newParentKey , key , 'first' ) ;
231+ newBlockMap = updateParentChild ( newBlockMap , newParentKey , key , 0 ) ;
243232 const prevSibling = block . getPrevSiblingKey ( ) ;
244233 if ( prevSibling != null ) {
245234 newBlockMap = updateSibling ( newBlockMap , prevSibling , newParentKey ) ;
@@ -266,7 +255,12 @@ const updateAsSiblingsChild = (
266255 ) ;
267256 break ;
268257 case 'previous' :
269- newBlockMap = updateParentChild ( newBlockMap , newParentKey , key , 'last' ) ;
258+ newBlockMap = updateParentChild (
259+ newBlockMap ,
260+ newParentKey ,
261+ key ,
262+ newParent . getChildKeys ( ) . count ( ) ,
263+ ) ;
270264 const nextSibling = block . getNextSiblingKey ( ) ;
271265 if ( nextSibling != null ) {
272266 newBlockMap = updateSibling ( newBlockMap , newParentKey , nextSibling ) ;
0 commit comments