Hardened reorder child invariants
Brian Vaughn committed
Apr 18, 2019 at 17:58 UTC
24736e4ff57832b9fcc1da8137729ae65a78124a
1 file changed
+16
-16
src/devtools/store.js
+16
-16
@@ -714,12 +714,7 @@ export default class Store extends EventEmitter {
714
weightDelta = -element.weight;
715
716
if (element.children.length > 0) {
717
- throw new Error(
718
- 'Fiber ' +
719
- id +
720
- ' was removed before its children. ' +
721
- 'This is a bug in React DevTools.'
722
- );
717
+ throw new Error(`Node ${id} was removed before its children.`);
718
}
719
720
this._idToElement.delete(id);
@@ -759,7 +754,7 @@ export default class Store extends EventEmitter {
754
case TREE_OPERATION_RESET_CHILDREN:
755
id = ((operations[i + 1]: any): number);
756
const numChildren = ((operations[i + 2]: any): number);
762
- const children = ((operations.slice(
757
+ const nextChildren = ((operations.slice(
758
i + 3,
759
i + 3 + numChildren
760
): any): Array<number>);
@@ -767,7 +762,7 @@ export default class Store extends EventEmitter {
762
i = i + 3 + numChildren;
763
764
if (__DEBUG__) {
770
- debug('Re-order', `Node ${id} children ${children.join(',')}`);
765
+ debug('Re-order', `Node ${id} children ${nextChildren.join(',')}`);
766
}
767
768
if (!this._idToElement.has(id)) {
@@ -777,23 +772,28 @@ export default class Store extends EventEmitter {
772
}
773
774
element = ((this._idToElement.get(id): any): Element);
775
+
776
const prevChildren = element.children;
781
- element.children = Array.from(children);
782
- if (element.children.length !== prevChildren.length) {
783
- throw new Error(
784
- 'Fiber ' +
785
- id +
786
- ' received a different number of children on reorder. ' +
787
- 'This is a bug in React DevTools.'
777
+ if (
778
+ nextChildren.length !== prevChildren.length ||
779
+ nextChildren.find(childID => {
780
+ const childElement = this._idToElement.get(childID);
781
+ return childElement == null || childElement.parentID !== id;
782
+ }) != null
783
+ ) {
784
+ throw Error(
785
+ `Children cannot be added or removed during a reorder operation.`
786
);
787
}
788
789
+ element.children = Array.from(nextChildren);
790
+
791
if (!element.isCollapsed) {
792
const prevWeight = element.weight;
793
794
let nextWeight = element.type === ElementTypeRoot ? 0 : 1;
795
796
- children.forEach(childID => {
796
+ nextChildren.forEach(childID => {
797
const child = ((this._idToElement.get(childID): any): Element);
798
nextWeight += child.isCollapsed ? 1 : child.weight;
799
});