Kill ReactMount.getNode/getID/purgeID with fire

This commit is contained in:
Ben Alpert
2015-10-17 20:38:45 -07:00
parent 796f8c353c
commit 4ba0e95a96
12 changed files with 33 additions and 550 deletions
-351
View File
@@ -28,7 +28,6 @@ var ReactUpdateQueue = require('ReactUpdateQueue');
var ReactUpdates = require('ReactUpdates');
var emptyObject = require('emptyObject');
var containsNode = require('containsNode');
var instantiateReactComponent = require('instantiateReactComponent');
var invariant = require('invariant');
var setInnerHTML = require('setInnerHTML');
@@ -36,7 +35,6 @@ var shouldUpdateReactComponent = require('shouldUpdateReactComponent');
var warning = require('warning');
var ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME;
var nodeCache = {};
var ELEMENT_NODE_TYPE = 1;
var DOC_NODE_TYPE = 9;
@@ -54,9 +52,6 @@ if (__DEV__) {
var rootElementsByReactRootID = {};
}
// Used to store breadth-first search state in findComponentRoot.
var findComponentRootReusableArray = [];
/**
* Finds the index of the first character
* that's not common between the two given strings.
@@ -99,33 +94,6 @@ function getReactRootID(container) {
return rootElement && internalGetID(rootElement);
}
/**
* Accessing node[ATTR_NAME] or calling getAttribute(ATTR_NAME) on a form
* element can return its control whose name or ID equals ATTR_NAME. All
* DOM nodes support `getAttributeNode` but this can also get called on
* other objects so just return '' if we're given something other than a
* DOM node (such as window).
*
* @param {?DOMElement|DOMWindow|DOMDocument|DOMTextNode} node DOM node.
* @return {string} ID of the supplied `domNode`.
*/
function getID(node) {
var id = internalGetID(node);
if (id) {
var cached = nodeCache[id];
// TODO: Fix this whole concept of "validity" -- the cache just shouldn't
// have nodes that have been unmounted.
invariant(
!cached || cached === node || !isValid(cached, id),
'ReactMount: Two valid but unequal nodes with the same `%s`: %s',
ATTR_NAME, id
);
nodeCache[id] = node;
}
return id;
}
function internalGetID(node) {
// If node is something like a window, document, or text node, none of
// which support attributes or a .getAttribute method, gracefully return
@@ -133,112 +101,6 @@ function internalGetID(node) {
return node && node.getAttribute && node.getAttribute(ATTR_NAME) || '';
}
/**
* Sets the React-specific ID of the given node.
*
* @param {DOMElement} node The DOM node whose ID will be set.
* @param {string} id The value of the ID attribute.
*/
function setID(node, id) {
var oldID = internalGetID(node);
if (oldID !== id) {
delete nodeCache[oldID];
}
node.setAttribute(ATTR_NAME, id);
nodeCache[id] = node;
}
/**
* Finds the node with the supplied ID if present in the cache.
*/
function getNodeIfCached(id) {
var node = nodeCache[id];
// TODO: Fix this whole concept of "validity" -- the cache just shouldn't have
// nodes that have been unmounted.
if (node && isValid(node, id)) {
return node;
}
}
/**
* Finds the node with the supplied React-generated DOM ID.
*
* @param {string} id A React-generated DOM ID.
* @return {DOMElement} DOM node with the suppled `id`.
* @internal
*/
function getNode(id) {
var node = getNodeIfCached(id);
if (node) {
return node;
} else {
return nodeCache[id] = ReactMount.findReactNodeByID(id);
}
}
/**
* A node is "valid" if it is contained by a currently mounted container.
*
* This means that the node does not have to be contained by a document in
* order to be considered valid.
*
* @param {?DOMElement} node The candidate DOM node.
* @param {string} id The expected ID of the node.
* @return {boolean} Whether the node is contained by a mounted container.
*/
function isValid(node, id) {
if (node) {
invariant(
internalGetID(node) === id,
'ReactMount: Unexpected modification of `%s`',
ATTR_NAME
);
var container = ReactMount.findReactContainerForID(id);
if (container && containsNode(container, node)) {
return true;
}
}
return false;
}
/**
* Causes the cache to forget about one React-specific ID.
*
* @param {string} id The ID to forget.
*/
function purgeID(id) {
delete nodeCache[id];
}
var deepestNodeSoFar = null;
function findDeepestCachedAncestorImpl(ancestorID) {
var ancestor = getNodeIfCached(ancestorID);
if (ancestor) {
deepestNodeSoFar = ancestor;
} else {
// This node isn't populated in the cache, so presumably none of its
// descendants are. Break out of the loop.
return false;
}
}
/**
* Return the deepest cached node whose ID is a prefix of `targetID`.
*/
function findDeepestCachedAncestor(targetID) {
deepestNodeSoFar = null;
ReactInstanceHandles.traverseAncestors(
targetID,
findDeepestCachedAncestorImpl
);
var foundNode = deepestNodeSoFar;
deepestNodeSoFar = null;
return foundNode;
}
/**
* Mounts this component and inserts it into the DOM.
*
@@ -344,47 +206,6 @@ function hasNonRootReactChild(node) {
ReactInstanceHandles.getReactRootIDFromNodeID(reactRootID) : false;
}
/**
* Returns the first (deepest) ancestor of a node which is rendered by this copy
* of React.
*/
function findFirstReactDOMImpl(node) {
// This node might be from another React instance, so we make sure not to
// examine the node cache here
for (; node && node.parentNode !== node; node = node.parentNode) {
if (node.nodeType !== 1) {
// Not a DOMElement, therefore not a React component
continue;
}
var nodeID = internalGetID(node);
if (!nodeID) {
continue;
}
var reactRootID = ReactInstanceHandles.getReactRootIDFromNodeID(nodeID);
// If containersByReactRootID contains the container we find by crawling up
// the tree, we know that this instance of React rendered the node.
// nb. isValid's strategy (with containsNode) does not work because render
// trees may be nested and we don't want a false positive in that case.
var current = node;
var lastID;
do {
lastID = internalGetID(current);
current = current.parentNode;
if (current == null) {
// The passed-in node has been detached from the container it was
// originally rendered into.
return null;
}
} while (lastID !== reactRootID);
if (current === containersByReactRootID[reactRootID]) {
return node;
}
}
return null;
}
/**
* Temporary (?) hack so that we can store all top-level pending updates on
* composites instead of having to worry about different types of components
@@ -794,162 +615,6 @@ var ReactMount = {
return true;
},
/**
* Finds the container DOM element that contains React component to which the
* supplied DOM `id` belongs.
*
* @param {string} id The ID of an element rendered by a React component.
* @return {?DOMElement} DOM element that contains the `id`.
*/
findReactContainerForID: function(id) {
var reactRootID = ReactInstanceHandles.getReactRootIDFromNodeID(id);
var container = containersByReactRootID[reactRootID];
if (__DEV__) {
var rootElement = rootElementsByReactRootID[reactRootID];
if (rootElement && rootElement.parentNode !== container) {
warning(
// Call internalGetID here because getID calls isValid which calls
// findReactContainerForID (this function).
internalGetID(rootElement) === reactRootID,
'ReactMount: Root element ID differed from reactRootID.'
);
var containerChild = container.firstChild;
if (containerChild &&
reactRootID === internalGetID(containerChild)) {
// If the container has a new child with the same ID as the old
// root element, then rootElementsByReactRootID[reactRootID] is
// just stale and needs to be updated. The case that deserves a
// warning is when the container is empty.
rootElementsByReactRootID[reactRootID] = containerChild;
} else {
warning(
false,
'ReactMount: Root element has been removed from its original ' +
'container. New container: %s',
rootElement.parentNode
);
}
}
}
return container;
},
/**
* Finds an element rendered by React with the supplied ID.
*
* @param {string} id ID of a DOM node in the React component.
* @return {DOMElement} Root DOM node of the React component.
*/
findReactNodeByID: function(id) {
var reactRoot = ReactMount.findReactContainerForID(id);
return ReactMount.findComponentRoot(reactRoot, id);
},
/**
* Traverses up the ancestors of the supplied node to find a node that is a
* DOM representation of a React component rendered by this copy of React.
*
* @param {*} node
* @return {?DOMEventTarget}
* @internal
*/
getFirstReactDOM: function(node) {
return findFirstReactDOMImpl(node);
},
/**
* Finds a node with the supplied `targetID` inside of the supplied
* `ancestorNode`. Exploits the ID naming scheme to perform the search
* quickly.
*
* @param {DOMEventTarget} ancestorNode Search from this root.
* @pararm {string} targetID ID of the DOM representation of the component.
* @return {DOMEventTarget} DOM node with the supplied `targetID`.
* @internal
*/
findComponentRoot: function(ancestorNode, targetID) {
var firstChildren = findComponentRootReusableArray;
var childIndex = 0;
var deepestAncestor = findDeepestCachedAncestor(targetID) || ancestorNode;
if (__DEV__) {
// This will throw on the next line; give an early warning
warning(
deepestAncestor != null,
'React can\'t find the root component node for data-reactid value ' +
'`%s`. If you\'re seeing this message, it probably means that ' +
'you\'ve loaded two copies of React on the page. At this time, only ' +
'a single copy of React can be loaded at a time.',
targetID
);
}
firstChildren[0] = deepestAncestor.firstChild;
firstChildren.length = 1;
while (childIndex < firstChildren.length) {
var child = firstChildren[childIndex++];
var targetChild;
while (child) {
var childID = ReactMount.getID(child);
if (childID) {
// Even if we find the node we're looking for, we finish looping
// through its siblings to ensure they're cached so that we don't have
// to revisit this node again. Otherwise, we make n^2 calls to getID
// when visiting the many children of a single node in order.
if (targetID === childID) {
targetChild = child;
} else if (ReactInstanceHandles.isAncestorIDOf(childID, targetID)) {
// If we find a child whose ID is an ancestor of the given ID,
// then we can be sure that we only want to search the subtree
// rooted at this child, so we can throw out the rest of the
// search state.
firstChildren.length = childIndex = 0;
firstChildren.push(child.firstChild);
}
} else {
// If this child had no ID, then there's a chance that it was
// injected automatically by the browser, as when a `<table>`
// element sprouts an extra `<tbody>` child as a side effect of
// `.innerHTML` parsing. Optimistically continue down this
// branch, but not before examining the other siblings.
firstChildren.push(child.firstChild);
}
child = child.nextSibling;
}
if (targetChild) {
// Emptying firstChildren/findComponentRootReusableArray is
// not necessary for correctness, but it helps the GC reclaim
// any nodes that were left at the end of the search.
firstChildren.length = 0;
return targetChild;
}
}
firstChildren.length = 0;
invariant(
false,
'findComponentRoot(..., %s): Unable to find element. This probably ' +
'means the DOM was unexpectedly mutated (e.g., by the browser), ' +
'usually due to forgetting a <tbody> when using tables, nesting tags ' +
'like <form>, <p>, or <a>, or using non-SVG elements in an <svg> ' +
'parent. ' +
'Try inspecting the child nodes of the element with React ID `%s`.',
targetID,
ReactMount.getID(ancestorNode)
);
},
_mountImageIntoNode: function(
markup,
container,
@@ -1056,22 +721,6 @@ var ReactMount = {
ReactDOMComponentTree.precacheNode(instance, container.firstChild);
}
},
/**
* React ID utilities.
*/
getReactRootID: getReactRootID,
getID: getID,
setID: setID,
getNode: getNode,
isValid: isValid,
purgeID: purgeID,
};
ReactPerf.measureMethods(ReactMount, 'ReactMount', {
@@ -218,61 +218,6 @@ describe('ReactMount', function() {
);
});
it('should not crash in node cache when unmounting', function() {
var Component = React.createClass({
render: function() {
// Add refs to some nodes so that they get traversed and cached
return (
<div ref="a">
<div ref="b">b</div>
{this.props.showC && <div>c</div>}
</div>
);
},
});
var container = document.createElement('container');
ReactDOM.render(<div><Component showC={false} /></div>, container);
// Right now, A and B are in the cache. When we add C, it won't get added to
// the cache (assuming markup-string mode).
ReactDOM.render(<div><Component showC={true} /></div>, container);
// Remove A, B, and C. Unmounting C shouldn't cause B to get recached.
ReactDOM.render(<div></div>, container);
// Add them back -- this shouldn't cause a cached node collision.
ReactDOM.render(<div><Component showC={true} /></div>, container);
ReactDOM.unmountComponentAtNode(container);
});
it('should not crash in node cache when unmounting, case 2', function() {
var A = React.createClass({
render: function() {
return <a key={this.props.innerKey}>{this.props.innerKey}</a>;
},
});
var Component = React.createClass({
render: function() {
return (
<b>
<i>{this.props.step === 1 && <q />}</i>
{this.props.step === 1 && <A innerKey={this.props.step} />}
</b>
);
},
});
var container = document.createElement('container');
ReactDOM.render(<Component step={1} />, container);
ReactDOM.render(<Component step={2} />, container);
ReactDOM.render(<Component step={1} />, container);
ReactMount.getID(container.querySelector('a'));
});
it('passes the correct callback context', function() {
var container = document.createElement('div');
var calls = 0;
@@ -17,8 +17,6 @@ jest
var React;
var ReactDOM;
var ReactDOMServer;
var ReactInstanceMap;
var ReactMount;
var getTestDocument;
@@ -46,14 +44,12 @@ describe('rendering React components at document', function() {
React = require('React');
ReactDOM = require('ReactDOM');
ReactDOMServer = require('ReactDOMServer');
ReactInstanceMap = require('ReactInstanceMap');
ReactMount = require('ReactMount');
getTestDocument = require('getTestDocument');
testDocument = getTestDocument();
});
it('should be able to get root component id for document node', function() {
it('should be able to adopt server markup', function() {
expect(testDocument).not.toBeUndefined();
var Root = React.createClass({
@@ -64,22 +60,24 @@ describe('rendering React components at document', function() {
<title>Hello World</title>
</head>
<body>
Hello world
{'Hello ' + this.props.hello}
</body>
</html>
);
},
});
var markup = ReactDOMServer.renderToString(<Root />);
var markup = ReactDOMServer.renderToString(<Root hello="world" />);
testDocument = getTestDocument(markup);
var component = ReactDOM.render(<Root />, testDocument);
var body = testDocument.body;
ReactDOM.render(<Root hello="world" />, testDocument);
expect(testDocument.body.innerHTML).toBe('Hello world');
// TODO: This is a bad test. I have no idea what this is testing.
// Node IDs is an implementation detail and not part of the public API.
var componentID = ReactMount.getReactRootID(testDocument);
expect(componentID).toBe(ReactInstanceMap.get(component)._rootNodeID);
ReactDOM.render(<Root hello="moon" />, testDocument);
expect(testDocument.body.innerHTML).toBe('Hello moon');
expect(body).toBe(testDocument.body);
});
it('should not be able to unmount component from document node', function() {
@@ -14,7 +14,6 @@
var DOMPropertyOperations = require('DOMPropertyOperations');
var LinkedValueUtils = require('LinkedValueUtils');
var ReactDOMComponentTree = require('ReactDOMComponentTree');
var ReactMount = require('ReactMount');
var ReactUpdates = require('ReactUpdates');
var assign = require('Object.assign');
@@ -189,18 +188,12 @@ function _handleChange(event) {
// This will throw if radio buttons rendered by different copies of React
// and the same name are rendered into the same form (same as #1939).
// That's probably okay; we don't support it just as we don't support
// mixing React with non-React.
var otherID = ReactMount.getID(otherNode);
invariant(
otherID,
'ReactDOMInput: Mixing React and non-React radio inputs with the ' +
'same `name` is not supported.'
);
var otherInstance = instancesByReactID[otherID];
// mixing React radio buttons with non-React ones.
var otherInstance = ReactDOMComponentTree.getInstanceFromNode(otherNode);
invariant(
otherInstance,
'ReactDOMInput: Unknown radio button ID %s.',
otherID
'ReactDOMInput: Mixing React and non-React radio inputs with the ' +
'same `name` is not supported.'
);
// If this is a controlled radio button group, forcing the input that
// was previously checked to update will cause it to be come re-checked
@@ -13,7 +13,6 @@
var DOMChildrenOperations = require('DOMChildrenOperations');
var ReactDOMIDOperations = require('ReactDOMIDOperations');
var ReactMount = require('ReactMount');
var ReactPerf = require('ReactPerf');
/**
@@ -37,7 +36,6 @@ var ReactComponentBrowserEnvironment = {
* @private
*/
unmountIDFromEnvironment: function(rootNodeID) {
ReactMount.purgeID(rootNodeID);
},
};
@@ -33,7 +33,6 @@ var ReactDOMInput = require('ReactDOMInput');
var ReactDOMOption = require('ReactDOMOption');
var ReactDOMSelect = require('ReactDOMSelect');
var ReactDOMTextarea = require('ReactDOMTextarea');
var ReactMount = require('ReactMount');
var ReactMultiChild = require('ReactMultiChild');
var ReactPerf = require('ReactPerf');
var ReactUpdateQueue = require('ReactUpdateQueue');
@@ -662,8 +661,6 @@ ReactDOMComponent.Mixin = {
ReactDOMComponentTree.precacheNode(this, el);
this._flags |= Flags.hasCachedChildNodes;
DOMPropertyOperations.setAttributeForID(el, this._rootNodeID);
// Populate node cache
ReactMount.getID(el);
this._updateDOMProperties(null, props, transaction);
var lazyTree = DOMLazyTree(el);
this._createInitialChildren(transaction, props, context, lazyTree);
@@ -18,7 +18,6 @@ var DOMPropertyOperations = require('DOMPropertyOperations');
var ReactComponentBrowserEnvironment =
require('ReactComponentBrowserEnvironment');
var ReactDOMComponentTree = require('ReactDOMComponentTree');
var ReactMount = require('ReactMount');
var assign = require('Object.assign');
var escapeTextContentForBrowser = require('escapeTextContentForBrowser');
@@ -99,10 +98,8 @@ assign(ReactDOMTextComponent.prototype, {
if (transaction.useCreateElement) {
var ownerDocument = nativeContainerInfo._ownerDocument;
var el = ownerDocument.createElement('span');
this._nativeNode = el;
ReactDOMComponentTree.precacheNode(this, el);
DOMPropertyOperations.setAttributeForID(el, rootID);
// Populate node cache
ReactMount.getID(el);
var lazyTree = DOMLazyTree(el);
DOMLazyTree.queueText(lazyTree, this._stringText);
return lazyTree;
@@ -16,7 +16,6 @@ var MorphingComponent;
var React;
var ReactDOM;
var ReactCurrentOwner;
var ReactMount;
var ReactPropTypes;
var ReactServerRendering;
var ReactTestUtils;
@@ -34,7 +33,6 @@ describe('ReactCompositeComponent', function() {
ReactCurrentOwner = require('ReactCurrentOwner');
ReactPropTypes = require('ReactPropTypes');
ReactTestUtils = require('ReactTestUtils');
ReactMount = require('ReactMount');
ReactServerRendering = require('ReactServerRendering');
ReactUpdates = require('ReactUpdates');
@@ -487,8 +485,6 @@ describe('ReactCompositeComponent', function() {
var container = document.createElement('div');
var innerUnmounted = false;
spyOn(ReactMount, 'purgeID').andCallThrough();
var Component = React.createClass({
render: function() {
return (
@@ -501,11 +497,6 @@ describe('ReactCompositeComponent', function() {
});
var Inner = React.createClass({
componentWillUnmount: function() {
// It's important that ReactMount.purgeID is called after any component
// lifecycle methods, because a componentWillUnmount implementation is
// likely to call ReactDOM.findDOMNode(this), which will repopulate the
// node cache after it's been cleared, causing a memory leak.
expect(ReactMount.purgeID.calls.length).toBe(0);
innerUnmounted = true;
},
render: function() {
@@ -516,12 +507,6 @@ describe('ReactCompositeComponent', function() {
ReactDOM.render(<Component />, container);
ReactDOM.unmountComponentAtNode(container);
expect(innerUnmounted).toBe(true);
// The text and both <div /> elements and their wrappers each call
// unmountIDFromEnvironment which calls purgeID, for a total of 3.
// TODO: Test the effect of this. E.g. does the node cache get repopulated
// after a getDOMNode call?
expect(ReactMount.purgeID.calls.length).toBe(3);
});
it('should warn when shouldComponentUpdate() returns undefined', function() {
@@ -13,9 +13,9 @@
var React;
var ReactDOM;
var ReactDOMComponentTree;
var ReactFragment;
var ReactTestUtils;
var ReactMount;
describe('ReactIdentity', function() {
@@ -23,14 +23,16 @@ describe('ReactIdentity', function() {
jest.resetModuleRegistry();
React = require('React');
ReactDOM = require('ReactDOM');
ReactDOMComponentTree = require('ReactDOMComponentTree');
ReactFragment = require('ReactFragment');
ReactTestUtils = require('ReactTestUtils');
ReactMount = require('ReactMount');
});
var idExp = /^\.[^.]+(.*)$/;
function checkID(child, expectedID) {
var actual = idExp.exec(ReactMount.getID(child));
// TODO: Node IDs are not public API; rewrite these tests.
var rootID = ReactDOMComponentTree.getInstanceFromNode(child)._rootNodeID;
var actual = idExp.exec(rootID);
var expected = idExp.exec(expectedID);
expect(actual).toBeTruthy();
expect(expected).toBeTruthy();
@@ -297,14 +299,16 @@ describe('ReactIdentity', function() {
var wrapped = <TestContainer first={instance0} second={instance1} />;
wrapped = ReactDOM.render(wrapped, document.createElement('div'));
var div = ReactDOM.findDOMNode(wrapped);
var beforeID = ReactMount.getID(ReactDOM.findDOMNode(wrapped).firstChild);
var beforeA = div.childNodes[0];
var beforeB = div.childNodes[1];
wrapped.swap();
var afterA = div.childNodes[1];
var afterB = div.childNodes[0];
var afterID = ReactMount.getID(ReactDOM.findDOMNode(wrapped).firstChild);
expect(beforeID).not.toEqual(afterID);
expect(beforeA).toBe(afterA);
expect(beforeB).toBe(afterB);
});
@@ -13,7 +13,6 @@
var React = require('React');
var ReactTestUtils = require('ReactTestUtils');
var ReactMount = require('ReactMount');
/**
* Ensure that all callbacks are invoked, passing this unique argument.
@@ -74,89 +73,6 @@ describe('ReactInstanceHandles', function() {
aggregatedArgs = [];
});
describe('findComponentRoot', function() {
it('should find the correct node with prefix sibling IDs', function() {
var parentNode = ReactTestUtils.renderIntoDocument(
<div>
<div />
{[<div key="x" />]}
</div>
);
var childNodeB = parentNode.childNodes[1];
expect(
ReactMount.getNode(
getNodeID(childNodeB)
)
).toBe(childNodeB);
});
it('should work around unidentified nodes', function() {
var parentNode = ReactTestUtils.renderIntoDocument(
<div>
{[<div key="x" />]}
</div>
);
var childNodeB = parentNode.childNodes[0];
// No ID on `childNodeA`.
var childNodeA = document.createElement('div');
parentNode.insertBefore(childNodeA, childNodeB);
expect(
ReactMount.getNode(
getNodeID(childNodeB)
)
).toBe(childNodeB);
});
it('should throw if a rendered element cannot be found', function() {
spyOn(console, 'error');
var parentNode = ReactTestUtils.renderIntoDocument(
<table>
<tr />
</table>
);
var childNodeA = parentNode.childNodes[0];
var childNodeB;
if (childNodeA.tagName === 'TR') {
childNodeB = childNodeA;
// No ID on `childNodeA`, it was "rendered by the browser".
childNodeA = document.createElement('tbody');
childNodeA.appendChild(childNodeB);
parentNode.appendChild(childNodeA);
} else {
childNodeB = childNodeA.childNodes[0];
}
expect(childNodeA.tagName).toBe('TBODY');
expect(
ReactMount.getNode(
getNodeID(childNodeB)
)
).toBe(childNodeB);
var junkID = getNodeID(childNodeB) + ':junk';
expect(function() {
ReactMount.getNode(
junkID
);
}).toThrow(
'findComponentRoot(..., ' + junkID + '): Unable to find element. ' +
'This probably means the DOM was unexpectedly mutated (e.g., by the ' +
'browser), usually due to forgetting a <tbody> when using tables, ' +
'nesting tags like <form>, <p>, or <a>, or using non-SVG elements in ' +
'an <svg> parent. Try inspecting the child nodes of the element with ' +
'React ID ``.'
);
expect(console.error.argsForCall.length).toBe(1);
expect(console.error.argsForCall[0][0]).toContain(
'<tr> cannot appear as a child of <table>'
);
});
});
describe('getReactRootIDFromNodeID', function() {
it('should support strings', function() {
var test = '.s_0_1.0..1';
@@ -13,8 +13,8 @@
var React = require('React');
var ReactDOM = require('ReactDOM');
var ReactDOMComponentTree = require('ReactDOMComponentTree');
var ReactInstanceMap = require('ReactInstanceMap');
var ReactMount = require('ReactMount');
var mapObject = require('mapObject');
@@ -190,7 +190,8 @@ function verifyDomOrderingAccurate(parentInstance, statusDisplays) {
var i;
var orderedDomIDs = [];
for (i = 0; i < statusDisplayNodes.length; i++) {
orderedDomIDs.push(ReactMount.getID(statusDisplayNodes[i]));
var inst = ReactDOMComponentTree.getInstanceFromNode(statusDisplayNodes[i]);
orderedDomIDs.push(inst._rootNodeID);
}
var orderedLogicalIDs = [];
+3 -3
View File
@@ -13,6 +13,7 @@
'use strict';
var DOMProperty = require('DOMProperty');
var ReactDOMComponentTree = require('ReactDOMComponentTree');
var ReactDefaultPerfAnalysis = require('ReactDefaultPerfAnalysis');
var ReactMount = require('ReactMount');
var ReactPerf = require('ReactPerf');
@@ -175,8 +176,7 @@ var ReactDefaultPerf = {
totalTime = performanceNow() - start;
if (fnName === '_mountImageIntoNode') {
var mountID = ReactMount.getID(args[1]);
ReactDefaultPerf._recordWrite(mountID, fnName, totalTime, args[0]);
ReactDefaultPerf._recordWrite('', fnName, totalTime, args[0]);
} else if (fnName === 'dangerouslyProcessChildrenUpdates') {
// special format
args[0].forEach(function(update) {
@@ -206,7 +206,7 @@ var ReactDefaultPerf = {
if (moduleName === 'EventPluginHub') {
id = id._rootNodeID;
} else if (typeof id === 'object') {
id = ReactMount.getID(args[0]);
id = ReactDOMComponentTree.getInstanceFromNode(args[0])._rootNodeID;
}
ReactDefaultPerf._recordWrite(
id,