Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 22 additions & 7 deletions src/core/ReactMount.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ if (__DEV__) {
var rootElementsByReactRootID = {};
}

// Used to store breadth-first search state in findComponentRoot.
var findComponentRootReusableArray = [];

/**
* @param {DOMElement} container DOM element that may contain a React component.
* @return {?string} A "reactRoot" ID, if a React component is rendered.
Expand Down Expand Up @@ -538,30 +541,39 @@ var ReactMount = {
* @internal
*/
findComponentRoot: function(ancestorNode, id) {
var firstChildren = [ancestorNode.firstChild];
var firstChildren = findComponentRootReusableArray;
var childIndex = 0;

firstChildren[0] = ancestorNode.firstChild;
firstChildren.length = 1;

while (childIndex < firstChildren.length) {
var child = firstChildren[childIndex++];
while (child) {
var childID = ReactMount.getID(child);
if (childID) {
if (id === childID) {
// 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 child;
} else if (ReactInstanceHandles.isAncestorIDOf(childID, id)) {
}

if (ReactInstanceHandles.isAncestorIDOf(childID, id)) {
// 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);

// Ignore the rest of this child's siblings and immediately
// continue the outer loop with child.firstChild as child.
break;
} else {
// TODO This should not be necessary if the ID hierarchy is
// correct, but is occasionally necessary if the DOM has been
// modified in unexpected ways.
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>`
Expand All @@ -570,10 +582,13 @@ var ReactMount = {
// branch, but not before examining the other siblings.
firstChildren.push(child.firstChild);
}

child = child.nextSibling;
}
}

firstChildren.length = 0;

if (__DEV__) {
console.error(
'Error while invoking `findComponentRoot` with the following ' +
Expand Down