void nsTransitionManager::UpdateAllThrottledStyles() { if (PR_CLIST_IS_EMPTY(&mElementData)) { // no throttled transitions, leave early mPresContext->TickLastUpdateThrottledStyle(); return; } if (mPresContext->ThrottledStyleIsUpToDate()) { // throttled transitions are up to date, leave early return; } mPresContext->TickLastUpdateThrottledStyle(); TimeStamp now = mPresContext->RefreshDriver()->MostRecentRefresh(); nsStyleChangeList changeList; // update each transitioning element by finding its root-most ancestor with a // transition, and flushing the style on that ancestor and all its descendants PRCList *next = PR_LIST_HEAD(&mElementData); while (next != &mElementData) { ElementTransitions* et = static_cast<ElementTransitions*>(next); next = PR_NEXT_LINK(next); if (et->mFlushGeneration == now) { // this element has been ticked already continue; } // element is initialised to the starting element (i.e., one we know has // a transition) and ends up with the root-most transitioning ancestor, // that is, the element where we begin updates. dom::Element* element = et->mElement; // make a list of ancestors nsTArray<dom::Element*> ancestors; do { ancestors.AppendElement(element); } while ((element = element->GetParentElement())); // walk down the ancestors until we find one with a throttled transition for (int32_t i = ancestors.Length() - 1; i >= 0; --i) { if (GetElementTransitions(ancestors[i], nsCSSPseudoElements::ePseudo_NotPseudoElement, false)) { element = ancestors[i]; break; } } nsIFrame* primaryFrame; if (element && (primaryFrame = nsLayoutUtils::GetStyleFrame(element))) { UpdateThrottledStylesForSubtree(element, primaryFrame->StyleContext()->GetParent(), changeList); } } RestyleManager* restyleManager = mPresContext->RestyleManager(); restyleManager->ProcessRestyledFrames(changeList); restyleManager->FlushOverflowChangedTracker(); }