in stetho/src/main/java/com/facebook/stetho/inspector/elements/ShadowDocument.java [299:337]
public void getGarbageElements(Accumulator<Object> accumulator) {
// This queue stores pairs of elements, [element, expectedParent]
// When we dequeue, we look at element's parentElement in the new view to see if it matches
// expectedParent. If it does, then it's garbage. For enqueueing roots, whose parents are
// null, since we can't enqueue null we instead enqueue the element twice.
Queue<Object> queue = new ArrayDeque<>();
// Initialize the queue with all disconnected tree roots (parentElement == null) which
// aren't the DOM root.
for (Object element : mRootElementChangesSet) {
ElementInfo newElementInfo = getElementInfo(element);
if (element != mRootElement && newElementInfo.parentElement == null) {
queue.add(element);
queue.add(element);
}
}
// BFS traversal from those elements in the old view of the tree and test each element
// to see if it's still within a disconnected sub-tree. We can tell if it's garbage if its
// parent element in the new view of the tree hasn't changed.
while (!queue.isEmpty()) {
final Object element = queue.remove();
final Object expectedParent0 = queue.remove();
final Object expectedParent = (element == expectedParent0) ? null : expectedParent0;
final ElementInfo newElementInfo = getElementInfo(element);
if (newElementInfo.parentElement == expectedParent) {
accumulator.store(element);
ElementInfo oldElementInfo = ShadowDocument.this.getElementInfo(element);
if (oldElementInfo != null) {
for (int i = 0, N = oldElementInfo.children.size(); i < N; ++i) {
queue.add(oldElementInfo.children.get(i));
queue.add(element);
}
}
}
}
}