Bug 1334036 - Part 13: Factor out ProcessPendingRestyles.
ProcessPendingRestyles and UpdateOnlyAnimationStyles do similar thing, so we
factor them out to a new function, DoProcessPendingRestyles, which has
one argument to indicate what kind of restyle we want.
MozReview-Commit-ID: D1urkIeJCHQ
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -439,17 +439,18 @@ ServoRestyleManager::FrameForPseudoEleme
}
MOZ_CRASH("Unkown pseudo-element given to "
"ServoRestyleManager::FrameForPseudoElement");
return nullptr;
}
void
-ServoRestyleManager::ProcessPendingRestyles()
+ServoRestyleManager::DoProcessPendingRestyles(TraversalRestyleBehavior
+ aRestyleBehavior)
{
MOZ_ASSERT(PresContext()->Document(), "No document? Pshaw!");
MOZ_ASSERT(!nsContentUtils::IsSafeToRunScript(), "Missing a script blocker!");
MOZ_ASSERT(!mInStyleRefresh, "Reentrant call?");
if (MOZ_UNLIKELY(!PresContext()->PresShell()->DidInitialize())) {
// PresShell::FlushPendingNotifications doesn't early-return in the case
// where the PreShell hasn't yet been initialized (and therefore we haven't
@@ -461,98 +462,38 @@ ServoRestyleManager::ProcessPendingResty
// Create a AnimationsWithDestroyedFrame during restyling process to
// stop animations and transitions on elements that have no frame at the end
// of the restyling process.
AnimationsWithDestroyedFrame animationsWithDestroyedFrame(this);
ServoStyleSet* styleSet = StyleSet();
nsIDocument* doc = PresContext()->Document();
+ bool animationOnly = aRestyleBehavior ==
+ TraversalRestyleBehavior::ForAnimationOnly;
// Ensure the refresh driver is active during traversal to avoid mutating
// 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) {
+ if (mHaveNonAnimationRestyles && !animationOnly) {
++mAnimationGeneration;
}
- while (styleSet->StyleDocument()) {
- ClearSnapshots();
-
- // 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);
+ while (animationOnly ? styleSet->StyleDocumentForAnimationOnly()
+ : styleSet->StyleDocument()) {
+ if (!animationOnly) {
+ ClearSnapshots();
}
- // Process the change hints.
- //
- // Unfortunately, the frame constructor can generate new change hints while
- // processing existing ones. We redirect those into a secondary queue and
- // iterate until there's nothing left.
- ReentrantChangeList newChanges;
- mReentrantChanges = &newChanges;
- while (!currentChanges.IsEmpty()) {
- ProcessRestyledFrames(currentChanges);
- MOZ_ASSERT(currentChanges.IsEmpty());
- for (ReentrantChange& change: newChanges) {
- currentChanges.AppendChange(change.mContent->GetPrimaryFrame(),
- change.mContent, change.mHint);
- }
- newChanges.Clear();
- }
- mReentrantChanges = nullptr;
-
- IncrementRestyleGeneration();
- }
-
- ClearSnapshots();
- 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();
-}
-
-void
-ServoRestyleManager::UpdateOnlyAnimationStyles()
-{
- MOZ_ASSERT(!mInStyleRefresh);
-
- // Bug 1365855: We also need to implement this for SMIL.
- bool doCSS = PresContext()->EffectCompositor()->HasPendingStyleUpdates();
- if (!doCSS) {
- return;
- }
-
- AnimationsWithDestroyedFrame animationsWithDestroyedFrame(this);
-
- ServoStyleSet* styleSet = StyleSet();
- nsIDocument* doc = PresContext()->Document();
- MOZ_ASSERT(doc, "Invalid document");
-
- // Ensure the refresh driver is active during traversal to avoid mutating
- // mActiveTimer and mMostRecentRefresh time.
- PresContext()->RefreshDriver()->MostRecentRefresh();
-
- mInStyleRefresh = true;
- while (styleSet->StyleDocumentForAnimationOnly()) {
// 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);
}
@@ -574,23 +515,48 @@ ServoRestyleManager::UpdateOnlyAnimation
}
mReentrantChanges = nullptr;
IncrementRestyleGeneration();
}
FlushOverflowChangedTracker();
+ if (!animationOnly) {
+ ClearSnapshots();
+ styleSet->AssertTreeIsClean();
+ mHaveNonAnimationRestyles = false;
+ }
mInStyleRefresh = false;
+ // Note: We are in the scope of |animationsWithDestroyedFrame|, so
+ // |mAnimationsWithDestroyedFrame| is still valid.
MOZ_ASSERT(mAnimationsWithDestroyedFrame);
mAnimationsWithDestroyedFrame->StopAnimationsForElementsWithoutFrames();
}
void
+ServoRestyleManager::ProcessPendingRestyles()
+{
+ DoProcessPendingRestyles(TraversalRestyleBehavior::Normal);
+}
+
+void
+ServoRestyleManager::UpdateOnlyAnimationStyles()
+{
+ // Bug 1365855: We also need to implement this for SMIL.
+ bool doCSS = PresContext()->EffectCompositor()->HasPendingStyleUpdates();
+ if (!doCSS) {
+ return;
+ }
+
+ DoProcessPendingRestyles(TraversalRestyleBehavior::ForAnimationOnly);
+}
+
+void
ServoRestyleManager::RestyleForInsertOrChange(nsINode* aContainer,
nsIContent* aChild)
{
//
// XXXbholley: We need the Gecko logic here to correctly restyle for things
// like :empty and positional selectors (though we may not need to post
// restyle events as agressively as the Gecko path does).
//
--- a/layout/base/ServoRestyleManager.h
+++ b/layout/base/ServoRestyleManager.h
@@ -135,16 +135,18 @@ private:
"style backend");
return PresContext()->StyleSet()->AsServo();
}
const SnapshotTable& Snapshots() const { return mSnapshots; }
void ClearSnapshots();
ServoElementSnapshot& SnapshotFor(mozilla::dom::Element* aElement);
+ void DoProcessPendingRestyles(TraversalRestyleBehavior aRestyleBehavior);
+
// We use a separate data structure from nsStyleChangeList because we need a
// frame to create nsStyleChangeList entries, and the primary frame may not be
// attached yet.
struct ReentrantChange {
nsCOMPtr<nsIContent> mContent;
nsChangeHint mHint;
};
typedef AutoTArray<ReentrantChange, 10> ReentrantChangeList;