Bug 1355758 - Update RestyleManager::mAnimationGeneration for non-animation update.
We use RestyleManager::mAnimationGeneration as the animation index of a
new created transition, and Element.getAnimations() uses this index to
sort the order of transitions. We increase mAnimationGeneration one per
restyle cycle if there is any non-animation update.
MozReview-Commit-ID: KmirBzI7CXi
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -50,32 +50,38 @@ ServoRestyleManager::PostRestyleEvent(El
// Processing change hints sometimes causes new change hints to be generated,
// and very occasionally, additional restyle hints. We collect the change
// hints manually to avoid re-traversing the DOM to find them.
if (mReentrantChanges && !aRestyleHint) {
mReentrantChanges->AppendElement(ReentrantChange { aElement, aMinChangeHint });
return;
}
+ if (aRestyleHint & ~eRestyle_AllHintsWithAnimations) {
+ mHaveNonAnimationRestyles = true;
+ }
+
Servo_NoteExplicitHints(aElement, aRestyleHint, aMinChangeHint);
}
/* static */ void
ServoRestyleManager::PostRestyleEventForAnimations(Element* aElement,
nsRestyleHint aRestyleHint)
{
Servo_NoteExplicitHints(aElement, aRestyleHint, nsChangeHint(0));
}
void
ServoRestyleManager::RebuildAllStyleData(nsChangeHint aExtraHint,
nsRestyleHint aRestyleHint)
{
StyleSet()->RebuildData();
+ mHaveNonAnimationRestyles = true;
+
// NOTE(emilio): GeckoRestlyeManager does a sync style flush, which seems
// not to be needed in my testing.
//
// If it is, we can just do a content flush and call ProcessPendingRestyles.
if (Element* root = mPresContext->Document()->GetRootElement()) {
PostRestyleEvent(root, aRestyleHint, aExtraHint);
}
@@ -382,16 +388,19 @@ ServoRestyleManager::ProcessPendingResty
// mActiveTimer and mMostRecentRefresh time.
PresContext()->RefreshDriver()->MostRecentRefresh();
// Perform the Servo traversal, and the post-traversal if required. We do this
// in a loop because certain rare paths in the frame constructor (like
// uninstalling XBL bindings) can trigger additional style validations.
mInStyleRefresh = true;
+ if (mHaveNonAnimationRestyles) {
+ ++mAnimationGeneration;
+ }
while (styleSet->StyleDocument()) {
// Recreate style contexts, and queue up change hints (which also handle
// lazy frame construction).
nsStyleChangeList currentChanges(StyleBackendType::Servo);
DocumentStyleRootIterator iter(doc);
while (Element* root = iter.GetNextStyleRoot()) {
ProcessPostTraversal(root, nullptr, styleSet, currentChanges);
}
@@ -414,16 +423,17 @@ ServoRestyleManager::ProcessPendingResty
}
mReentrantChanges = nullptr;
IncrementRestyleGeneration();
}
FlushOverflowChangedTracker();
+ mHaveNonAnimationRestyles = false;
mInStyleRefresh = false;
styleSet->AssertTreeIsClean();
// Note: We are in the scope of |animationsWithDestroyedFrame|, so
// |mAnimationsWithDestroyedFrame| is still valid.
MOZ_ASSERT(mAnimationsWithDestroyedFrame);
mAnimationsWithDestroyedFrame->StopAnimationsForElementsWithoutFrames();
}
--- a/layout/base/ServoRestyleManager.h
+++ b/layout/base/ServoRestyleManager.h
@@ -143,13 +143,20 @@ private:
nsCOMPtr<nsIContent> mContent;
nsChangeHint mHint;
};
typedef AutoTArray<ReentrantChange, 10> ReentrantChangeList;
// Only non-null while processing change hints. See the comment in
// ProcessPendingRestyles.
ReentrantChangeList* mReentrantChanges;
+
+ // We use this flag to track if the current restyle contains any non-animation
+ // update, which triggers a normal restyle, and so there might be any new
+ // transition created later. Therefore, if this flag is true, we need to
+ // increase mAnimationGeneration before creating new transitions, so their
+ // creation sequence will be correct.
+ bool mHaveNonAnimationRestyles = false;
};
} // namespace mozilla
#endif // mozilla_ServoRestyleManager_h