void HTMLImport::recalcTreeState(HTMLImport* root) { WillBeHeapHashMap<RawPtrWillBeMember<HTMLImport>, HTMLImportState> snapshot; WillBeHeapVector<RawPtrWillBeMember<HTMLImport>> updated; for (HTMLImport* i = root; i; i = traverseNext(i)) { snapshot.add(i, i->state()); i->m_state = HTMLImportState::invalidState(); } // The post-visit DFS order matters here because // HTMLImportStateResolver in recalcState() Depends on // |m_state| of its children and precedents of ancestors. // Accidental cycle dependency of state computation is prevented // by invalidateCachedState() and isStateCacheValid() check. for (HTMLImport* i = traverseFirstPostOrder(root); i; i = traverseNextPostOrder(i)) { ASSERT(!i->m_state.isValid()); i->m_state = HTMLImportStateResolver(i).resolve(); HTMLImportState newState = i->state(); HTMLImportState oldState = snapshot.get(i); // Once the state reaches Ready, it shouldn't go back. ASSERT(!oldState.isReady() || oldState <= newState); if (newState != oldState) updated.append(i); } for (size_t i = 0; i < updated.size(); ++i) updated[i]->stateDidChange(); }
TEST(TreeNodeTest, TraverseNextPostORder) { TrioWithGrandChild trio; trio.appendChildren(); TestTree* order[] = {trio.firstChild.get(), trio.grandChild.get(), trio.middleChild.get(), trio.lastChild.get(), trio.root.get()}; unsigned orderIndex = 0; for (TestTree *node = traverseFirstPostOrder(trio.root.get()); node; node = traverseNextPostOrder(node), orderIndex++) EXPECT_EQ(node, order[orderIndex]); EXPECT_EQ(orderIndex, sizeof(order) / sizeof(TestTree*)); }