Devtools should be able to clean up the tree on client rendering

This commit is contained in:
Dan Abramov
2016-04-20 19:01:24 +01:00
parent 367594a213
commit af3603ea2f
5 changed files with 89 additions and 45 deletions

View File

@@ -73,17 +73,17 @@ var ReactDebugTool = {
onSetText(debugID, text) {
emitEvent('onSetText', debugID, text);
},
onMountRootComponent(internalInstance) {
emitEvent('onMountRootComponent', internalInstance);
onMountRootComponent(debugID) {
emitEvent('onMountRootComponent', debugID);
},
onMountComponent(internalInstance) {
emitEvent('onMountComponent', internalInstance);
onMountComponent(debugID) {
emitEvent('onMountComponent', debugID);
},
onUpdateComponent(internalInstance) {
emitEvent('onUpdateComponent', internalInstance);
onUpdateComponent(debugID) {
emitEvent('onUpdateComponent', debugID);
},
onUnmountComponent(internalInstance) {
emitEvent('onUnmountComponent', internalInstance);
onUnmountComponent(debugID) {
emitEvent('onUnmountComponent', debugID);
},
};

View File

@@ -22,22 +22,22 @@ describe('ReactDebugTool', () => {
function createDevtool() {
var tree = {};
function updateTree(debugID, update) {
if (!tree[debugID]) {
tree[debugID] = {};
function updateTree(id, update) {
if (!tree[id]) {
tree[id] = {};
}
update(tree[debugID]);
update(tree[id]);
}
function getTree(debugID, includeOwner) {
var item = tree[debugID];
function getTree(id, includeOwner) {
var item = tree[id];
var result = {
isComposite: item.isComposite,
displayName: item.displayName,
};
if (item.childDebugIDs) {
result.children = item.childDebugIDs.map(childDebugID =>
getTree(childDebugID, includeOwner)
if (item.childIDs) {
result.children = item.childIDs.map(childID =>
getTree(childID, includeOwner)
);
}
if (item.text != null) {
@@ -49,29 +49,57 @@ describe('ReactDebugTool', () => {
return result;
}
function purgeTree(id) {
var item = tree[id];
if (!item) {
return;
}
var {childIDs} = item;
delete tree[id];
if (childIDs) {
childIDs.forEach(purgeTree);
}
}
return {
onSetIsComposite(debugID, isComposite) {
updateTree(debugID, item => item.isComposite = isComposite);
onSetIsComposite(id, isComposite) {
updateTree(id, item => item.isComposite = isComposite);
},
onSetDisplayName(debugID, displayName) {
updateTree(debugID, item => item.displayName = displayName);
onSetDisplayName(id, displayName) {
updateTree(id, item => item.displayName = displayName);
},
onSetChildren(debugID, childDebugIDs) {
childDebugIDs.forEach(childDebugID => {
var childItem = tree[childDebugID];
onSetChildren(id, childIDs) {
childIDs.forEach(childID => {
var childItem = tree[childID];
expect(childItem).toBeDefined();
expect(childItem.isComposite).toBeDefined();
expect(childItem.displayName).toBeDefined();
expect(childItem.childDebugIDs || childItem.text).toBeDefined();
expect(childItem.childIDs || childItem.text).toBeDefined();
});
updateTree(debugID, item => item.childDebugIDs = childDebugIDs);
updateTree(id, item => item.childIDs = childIDs);
},
onSetOwner(debugID, ownerDebugID) {
updateTree(debugID, item => item.ownerDebugID = ownerDebugID);
onSetOwner(id, ownerDebugID) {
updateTree(id, item => item.ownerDebugID = ownerDebugID);
},
onSetText(debugID, text) {
updateTree(debugID, item => item.text = text);
onSetText(id, text) {
updateTree(id, item => item.text = text);
},
onUnmountComponent(id) {
purgeTree(id);
},
getRegisteredDebugIDs() {
return Object.keys(tree);
},
getTree(rootDebugID, includeOwner) {
return getTree(rootDebugID, includeOwner);
},
@@ -119,6 +147,9 @@ describe('ReactDebugTool', () => {
);
expect(actualTree).toEqual(expectedTree);
});
ReactDOM.unmountComponentAtNode(node);
expect(devtool.getRegisteredDebugIDs()).toEqual([]);
}
describe('mount', () => {

View File

@@ -349,7 +349,7 @@ var ReactMount = {
instancesByReactRootID[wrapperID] = componentInstance;
if (__DEV__) {
ReactInstrumentation.debugTool.onMountRootComponent(componentInstance);
ReactInstrumentation.debugTool.onMountRootComponent(componentInstance._debugID);
}
return componentInstance;

View File

@@ -453,6 +453,7 @@ function ReactDOMComponent(element) {
this._flags = 0;
if (__DEV__) {
this._ancestorInfo = null;
this._contentDebugID = null;
}
}
@@ -758,11 +759,11 @@ ReactDOMComponent.Mixin = {
if (contentToUse != null) {
// TODO: Validate that text is allowed as a child of this node
if (__DEV__) {
var inlinedTextDebugID = this._debugID + '#text';
ReactInstrumentation.debugTool.onSetIsComposite(inlinedTextDebugID, false);
ReactInstrumentation.debugTool.onSetDisplayName(inlinedTextDebugID, '#text');
ReactInstrumentation.debugTool.onSetText(inlinedTextDebugID, '' + contentToUse);
ReactInstrumentation.debugTool.onSetChildren(this._debugID, [inlinedTextDebugID]);
this._contentDebugID = this._debugID + '#text';
ReactInstrumentation.debugTool.onSetIsComposite(this._contentDebugID, false);
ReactInstrumentation.debugTool.onSetDisplayName(this._contentDebugID, '#text');
ReactInstrumentation.debugTool.onSetText(this._contentDebugID, '' + contentToUse);
ReactInstrumentation.debugTool.onSetChildren(this._debugID, [this._contentDebugID]);
}
DOMLazyTree.queueText(lazyTree, contentToUse);
} else if (childrenToUse != null) {
@@ -1020,11 +1021,11 @@ ReactDOMComponent.Mixin = {
if (lastContent !== nextContent) {
this.updateTextContent('' + nextContent);
if (__DEV__) {
var inlinedTextDebugID = this._debugID + '#text';
ReactInstrumentation.debugTool.onSetIsComposite(inlinedTextDebugID, false);
ReactInstrumentation.debugTool.onSetDisplayName(inlinedTextDebugID, '#text');
ReactInstrumentation.debugTool.onSetText(inlinedTextDebugID, '' + nextContent);
ReactInstrumentation.debugTool.onSetChildren(this._debugID, [inlinedTextDebugID]);
this._contentDebugID = this._debugID + '#text';
ReactInstrumentation.debugTool.onSetIsComposite(this._contentDebugID, false);
ReactInstrumentation.debugTool.onSetDisplayName(this._contentDebugID, '#text');
ReactInstrumentation.debugTool.onSetText(this._contentDebugID, '' + nextContent);
ReactInstrumentation.debugTool.onSetChildren(this._debugID, [this._contentDebugID]);
}
}
} else if (nextHtml != null) {
@@ -1035,6 +1036,13 @@ ReactDOMComponent.Mixin = {
ReactInstrumentation.debugTool.onSetChildren(this._debugID, []);
}
} else if (nextChildren != null) {
if (__DEV__) {
if (this._contentDebugID) {
ReactInstrumentation.debugTool.onUnmountComponent(this._contentDebugID);
this._contentDebugID = null;
}
}
this.updateChildren(nextChildren, transaction, context);
}
},
@@ -1096,6 +1104,11 @@ ReactDOMComponent.Mixin = {
this._rootNodeID = null;
this._domID = null;
this._wrapperState = null;
if (this._contentDebugID) {
ReactInstrumentation.debugTool.onUnmountComponent(this._contentDebugID);
this._contentDebugID = null;
}
},
getPublicInstance: function() {

View File

@@ -53,7 +53,7 @@ var ReactReconciler = {
transaction.getReactMountReady().enqueue(attachRefs, internalInstance);
}
if (__DEV__) {
ReactInstrumentation.debugTool.onMountComponent(internalInstance);
ReactInstrumentation.debugTool.onMountComponent(internalInstance._debugID);
}
return markup;
},
@@ -76,7 +76,7 @@ var ReactReconciler = {
ReactRef.detachRefs(internalInstance, internalInstance._currentElement);
internalInstance.unmountComponent(safely);
if (__DEV__) {
ReactInstrumentation.debugTool.onUnmountComponent(internalInstance);
ReactInstrumentation.debugTool.onUnmountComponent(internalInstance._debugID);
}
},
@@ -128,7 +128,7 @@ var ReactReconciler = {
}
if (__DEV__) {
ReactInstrumentation.debugTool.onUpdateComponent(internalInstance);
ReactInstrumentation.debugTool.onUpdateComponent(internalInstance._debugID);
}
},
@@ -145,7 +145,7 @@ var ReactReconciler = {
) {
internalInstance.performUpdateIfNecessary(transaction);
if (__DEV__) {
ReactInstrumentation.debugTool.onUpdateComponent(internalInstance);
ReactInstrumentation.debugTool.onUpdateComponent(internalInstance._debugID);
}
},