Add react component names to JSC heap capture

Differential Revision: D3709253

fbshipit-source-id: dc158d6a096c3e91baeadbaafbf14904493392aa
This commit is contained in:
Charles Dick 2016-08-16 13:49:22 -07:00 committed by Facebook Github Bot 9
parent 6df41d5184
commit d54b3b8701
2 changed files with 102 additions and 50 deletions

View File

@ -17,11 +17,45 @@ return'Function '+ref.value.name;
return ref.type;
}
function idGetProp(refs,id,prop){
var ref=refs[id];
if(ref&&ref.edges){
var edges=ref.edges;
for(var edgeId in edges){
if(edges[edgeId]===prop){
return edgeId;
}
}
}
return undefined;
}
function idPropForEach(refs,id,callback){
var ref=refs[id];
if(ref&&ref.edges){
var edges=ref.edges;
for(var edgeId in edges){
callback(edges[edgeId],edgeId);
}
}
}
function getInternalInstanceName(refs,id){
var elementId=idGetProp(refs,id,'_currentElement');
var typeId=idGetProp(refs,elementId,'type');
var typeRef=refs[typeId];
if(typeRef&&typeRef.type==='Function'&&typeRef.value){
return typeRef.value.name;
}else{
return'<unknown component>';
}
}
function registerReactComponentTreeImpl(refs,registry,parents,inEdgeNames,trees,id){
if(parents[id]===undefined){
// not a component
}else if(parents[id]===null){
trees[id]=registry.insert(registry.root,'<internalInstance>');
trees[id]=registry.insert(registry.root,getInternalInstanceName(refs,id));
}else{
var parent=parents[id];
var inEdgeName=inEdgeNames[id];
@ -44,34 +78,31 @@ return trees[id];
function registerReactComponentTree(refs,registry){
// build list of parents for react interal instances, so we can connect a tree
var parents={};
var inEdgeNames={};
for(var id in refs){
var ref=refs[id];
for(var linkId in ref.edges){
if(linkId!=='0x0'){
var name=ref.edges[linkId];
var inEdgeNames={};var _loop=function _loop(
id){
idPropForEach(refs,id,function(name,propId){
if(propId!=='0x0'){
if(name==='_renderedChildren'){
if(parents[id]===undefined){
// mark that we are a react component, even if we don't have a parent
parents[id]=null;
}
var childrenRef=refs[linkId];
for(var childId in childrenRef.edges){
var linkName=childrenRef.edges[childId];
if(linkName.startsWith('.')){
parents[childId]=id;
inEdgeNames[childId]=linkName;
}
idPropForEach(refs,propId,function(childName,childPropId){
if(childName.startsWith('.')){
parents[childPropId]=id;
inEdgeNames[childPropId]=childName+': '+
getInternalInstanceName(refs,childPropId);
}
});
}else if(name==='_renderedComponent'){
if(parents[id]===undefined){
parents[id]=null;
}
parents[linkId]=id;
inEdgeNames[linkId]='_renderedComponent';
}
parents[propId]=id;
inEdgeNames[propId]=getInternalInstanceName(refs,propId);
}
}
});};for(var id in refs){_loop(id);
}
// build tree of react internal instances (since that's what has the structure)
var trees={};
@ -80,14 +111,9 @@ registerReactComponentTreeImpl(refs,registry,parents,inEdgeNames,trees,_id);
}
// hook in components by looking at their _reactInternalInstance fields
for(var _id2 in refs){
var _ref=refs[_id2];
for(var _linkId in _ref.edges){
var _name=_ref.edges[_linkId];
if(_name==='_reactInternalInstance'){
if(trees[_linkId]!==undefined){
trees[_id2]=registry.insert(trees[_linkId],'<component>');
}
}
var internalInstance=idGetProp(refs,_id2,'_reactInternalInstance');
if(internalInstance&&trees[internalInstance]){
trees[_id2]=trees[internalInstance];
}
}
return trees;
@ -106,7 +132,7 @@ breadth.push(id);
}
while(breadth.length>0){
var nextBreadth=[];var _loop=function _loop(
var nextBreadth=[];var _loop2=function _loop2(
_i){
var id=breadth[_i];
var ref=refs[id];
@ -147,7 +173,7 @@ reactComponentTree[edgeId]=reactComponentTree[id];
}
}
}
}};for(var _i=0;_i<breadth.length;_i++){_loop(_i);
}};for(var _i=0;_i<breadth.length;_i++){_loop2(_i);
}
breadth=nextBreadth;
}

View File

@ -17,11 +17,45 @@ function getTypeName(ref) {
return ref.type;
}
function idGetProp(refs, id, prop) {
const ref = refs[id];
if (ref && ref.edges) {
const edges = ref.edges;
for (const edgeId in edges) {
if (edges[edgeId] === prop) {
return edgeId;
}
}
}
return undefined;
}
function idPropForEach(refs, id, callback) {
const ref = refs[id];
if (ref && ref.edges) {
const edges = ref.edges;
for (const edgeId in edges) {
callback(edges[edgeId], edgeId);
}
}
}
function getInternalInstanceName(refs, id) {
const elementId = idGetProp(refs, id, '_currentElement');
const typeId = idGetProp(refs, elementId, 'type');
const typeRef = refs[typeId];
if (typeRef && typeRef.type === 'Function' && typeRef.value) {
return typeRef.value.name;
} else {
return '<unknown component>';
}
}
function registerReactComponentTreeImpl(refs, registry, parents, inEdgeNames, trees, id) {
if (parents[id] === undefined) {
// not a component
} else if (parents[id] === null) {
trees[id] = registry.insert(registry.root, '<internalInstance>');
trees[id] = registry.insert(registry.root, getInternalInstanceName(refs, id));
} else {
const parent = parents[id];
const inEdgeName = inEdgeNames[id];
@ -46,32 +80,29 @@ function registerReactComponentTree(refs, registry) {
const parents = {};
const inEdgeNames = {};
for (const id in refs) {
const ref = refs[id];
for (const linkId in ref.edges) {
if (linkId !== '0x0') {
const name = ref.edges[linkId];
idPropForEach(refs, id, (name, propId) => {
if (propId !== '0x0') {
if (name === '_renderedChildren') {
if (parents[id] === undefined) {
// mark that we are a react component, even if we don't have a parent
parents[id] = null;
}
const childrenRef = refs[linkId];
for (const childId in childrenRef.edges) {
const linkName = childrenRef.edges[childId];
if (linkName.startsWith('.')) {
parents[childId] = id;
inEdgeNames[childId] = linkName;
idPropForEach(refs, propId, (childName, childPropId) => {
if (childName.startsWith('.')) {
parents[childPropId] = id;
inEdgeNames[childPropId] = childName + ': '
+ getInternalInstanceName(refs, childPropId);
}
}
});
} else if (name === '_renderedComponent') {
if (parents[id] === undefined) {
parents[id] = null;
}
parents[linkId] = id;
inEdgeNames[linkId] = '_renderedComponent';
parents[propId] = id;
inEdgeNames[propId] = getInternalInstanceName(refs, propId);
}
}
}
});
}
// build tree of react internal instances (since that's what has the structure)
const trees = {};
@ -80,14 +111,9 @@ function registerReactComponentTree(refs, registry) {
}
// hook in components by looking at their _reactInternalInstance fields
for (const id in refs) {
const ref = refs[id];
for (const linkId in ref.edges) {
const name = ref.edges[linkId];
if (name === '_reactInternalInstance') {
if (trees[linkId] !== undefined) {
trees[id] = registry.insert(trees[linkId], '<component>');
}
}
const internalInstance = idGetProp(refs, id, '_reactInternalInstance');
if (internalInstance && trees[internalInstance]) {
trees[id] = trees[internalInstance];
}
}
return trees;