@samitouri / QOS-React-2 / commits / 24736e4ff5

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 });