@@ -1206,6 +1206,8 @@ class BNode<K,V> {
1206
1206
// If this is an internal node, _keys[i] is the highest key in children[i].
1207
1207
keys : K [ ] ;
1208
1208
values : V [ ] ;
1209
+ // True if this node might multiple parents (equivalently: could be in multiple b-trees).
1210
+ // This means it must be cloned before being mutated to avoid changing an unrelated tree.
1209
1211
isShared : true | undefined ;
1210
1212
get isLeaf ( ) { return ( this as any ) . children === undefined ; }
1211
1213
@@ -1528,6 +1530,10 @@ class BNodeInternal<K,V> extends BNode<K,V> {
1528
1530
// keys[i] caches the value of children[i].maxKey().
1529
1531
children : BNode < K , V > [ ] ;
1530
1532
1533
+ /**
1534
+ * This does not mark `children` as shared, so it is the responsibility of the caller
1535
+ * to ensure that either children are marked shared, or it are not included in another tree.
1536
+ */
1531
1537
constructor ( children : BNode < K , V > [ ] , keys ?: K [ ] ) {
1532
1538
if ( ! keys ) {
1533
1539
keys = [ ] ;
@@ -1550,7 +1556,7 @@ class BNodeInternal<K,V> extends BNode<K,V> {
1550
1556
return this ;
1551
1557
var nu = new BNodeInternal < K , V > ( this . children . slice ( 0 ) , this . keys . slice ( 0 ) ) ;
1552
1558
for ( var i = 0 ; i < nu . children . length ; i ++ )
1553
- nu . children [ i ] = nu . children [ i ] . greedyClone ( ) ;
1559
+ nu . children [ i ] = nu . children [ i ] . greedyClone ( force ) ;
1554
1560
return nu ;
1555
1561
}
1556
1562
@@ -1666,12 +1672,22 @@ class BNodeInternal<K,V> extends BNode<K,V> {
1666
1672
}
1667
1673
}
1668
1674
1675
+ /**
1676
+ * Inserts `child` at index `i`.
1677
+ * This does not mark `child` as shared, so it is the responsibility of the caller
1678
+ * to ensure that either child is marked shared, or it is not included in another tree.
1679
+ */
1669
1680
insert ( i : index , child : BNode < K , V > ) {
1670
1681
this . children . splice ( i , 0 , child ) ;
1671
1682
this . keys . splice ( i , 0 , child . maxKey ( ) ) ;
1672
1683
}
1673
1684
1685
+ /**
1686
+ * Split this node.
1687
+ * Modifies this to remove the second half of the items, returning a separate node containing them.
1688
+ */
1674
1689
splitOffRightSide ( ) {
1690
+ // assert !this.isShared;
1675
1691
var half = this . children . length >> 1 ;
1676
1692
return new BNodeInternal < K , V > ( this . children . splice ( half ) , this . keys . splice ( half ) ) ;
1677
1693
}
@@ -1765,11 +1781,26 @@ class BNodeInternal<K,V> extends BNode<K,V> {
1765
1781
return false ;
1766
1782
}
1767
1783
1784
+ /**
1785
+ * Move children from `rhs` into this.
1786
+ * `rhs` must be part of this tree, and be removed from it after this call
1787
+ * (otherwise isShared for its children could be incorrect).
1788
+ */
1768
1789
mergeSibling ( rhs : BNode < K , V > , maxNodeSize : number ) {
1769
1790
// assert !this.isShared;
1770
1791
var oldLength = this . keys . length ;
1771
1792
this . keys . push . apply ( this . keys , rhs . keys ) ;
1772
- this . children . push . apply ( this . children , ( rhs as any as BNodeInternal < K , V > ) . children ) ;
1793
+ const rhsChildren = ( rhs as any as BNodeInternal < K , V > ) . children ;
1794
+ this . children . push . apply ( this . children , rhsChildren ) ;
1795
+
1796
+ if ( rhs . isShared ) {
1797
+ // Because rhs might continue to be used in another tree since it is shared,
1798
+ // this is adding a parent to its children instead of just changing what their parent is.
1799
+ // Thus they need to be marked as shared.
1800
+ for ( var i = 0 ; i < rhsChildren . length ; i ++ )
1801
+ rhsChildren [ i ] . isShared = true ;
1802
+ }
1803
+
1773
1804
// If our children are themselves almost empty due to a mass-delete,
1774
1805
// they may need to be merged too (but only the oldLength-1 and its
1775
1806
// right sibling should need this).
0 commit comments