diff options
author | alancutter <alancutter@chromium.org> | 2015-10-15 22:58:26 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-10-16 05:59:23 +0000 |
commit | 1737f9e86e74990aad0e9693ebf247c8ffbb86f9 (patch) | |
tree | a2e61a9a0e9c44febf2410e4a55276d44dcab9a9 | |
parent | eb7f57c9808ff03e537d1f79fb0cc57ebb19d34f (diff) | |
download | chromium_src-1737f9e86e74990aad0e9693ebf247c8ffbb86f9.zip chromium_src-1737f9e86e74990aad0e9693ebf247c8ffbb86f9.tar.gz chromium_src-1737f9e86e74990aad0e9693ebf247c8ffbb86f9.tar.bz2 |
Preserve running CSS Animations across changes to animation styles according to same name index
We currently only keep track of the last animation that used
a given @keyframes name. If multiple animations use the same
@keyframes rule we fail to update their timing input correctly
as animation styles are updated.
This change makes us track animation-name references to running
animations based on name and name index (nth occurrence of name)
rather than just name.
This behaviour does not conform to any spec text as the
specification does not dictate what to do in this scenario:
"Need to specify better handling of dynamic changes of animation-name"
https://drafts.csswg.org/css-animations-1/#other-open-issues
The behaviour introduced in this patch is arbitrary though
better than the existing behaviour of ignoring running
animations and crashing debug on timing updates.
BUG=487092
Review URL: https://codereview.chromium.org/1402143004
Cr-Commit-Position: refs/heads/master@{#354457}
5 files changed, 245 insertions, 84 deletions
diff --git a/third_party/WebKit/LayoutTests/animations/multiple-same-animations-asan-crash.html b/third_party/WebKit/LayoutTests/animations/multiple-same-animations-asan-crash.html index 42a4fdd..3a22397 100644 --- a/third_party/WebKit/LayoutTests/animations/multiple-same-animations-asan-crash.html +++ b/third_party/WebKit/LayoutTests/animations/multiple-same-animations-asan-crash.html @@ -16,8 +16,6 @@ requestAnimationFrame(function() { // Force the next style recalc to be non-animation triggered. target.style.color = 'blue'; requestAnimationFrame(function() { - // Clear the running animations to avoid hitting a debug assertion. (crbug.com/487092) - target.style.animation = 'none'; asyncHandle.done(); }); }); diff --git a/third_party/WebKit/LayoutTests/animations/multiple-same-name-css-animations.html b/third_party/WebKit/LayoutTests/animations/multiple-same-name-css-animations.html new file mode 100644 index 0000000..fe1c3f2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/animations/multiple-same-name-css-animations.html @@ -0,0 +1,139 @@ +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<style> +@keyframes a {} +@keyframes b {} +</style> +<div id="target"></div> +<script> +function setAnimationProperty(value) { + target.style.animation = value; + target.offsetTop; +} + +function getAnimations() { + return document.timeline.getAnimations(); +} + +function clearAnimations() { + setAnimationProperty('none'); + assert_equals(getAnimations().length, 0); +} + +test(() => { + clearAnimations(); + setAnimationProperty('a 1000ms 1500ms forwards, a 2000ms 2500ms backwards, a 3000ms 3500ms both'); + var animations = getAnimations(); + assert_equals(animations.length, 3); + assert_equals(animations[0].effect.timing.duration, 1000); + assert_equals(animations[0].effect.timing.delay, 1500); + assert_equals(animations[0].effect.timing.fill, 'forwards'); + + assert_equals(animations[1].effect.timing.duration, 2000); + assert_equals(animations[1].effect.timing.delay, 2500); + assert_equals(animations[1].effect.timing.fill, 'backwards'); + + assert_equals(animations[2].effect.timing.duration, 3000); + assert_equals(animations[2].effect.timing.delay, 3500); + assert_equals(animations[2].effect.timing.fill, 'both'); +}, 'Multiple same animation names should start multiple animations.'); + +test(() => { + clearAnimations(); + + setAnimationProperty('a 1500ms paused, a 2500ms paused, a 3500ms paused'); + var animations = getAnimations(); + assert_equals(animations.length, 3); + animations[0].currentTime = 1000; + animations[1].currentTime = 2000; + animations[2].currentTime = 3000; + + setAnimationProperty('a 1750ms paused, a 2750ms paused, a 3750ms paused'); + animations = getAnimations(); + assert_equals(animations.length, 3); + + assert_equals(animations[0].currentTime, 1000); + assert_equals(animations[0].effect.timing.duration, 1750); + + assert_equals(animations[1].currentTime, 2000); + assert_equals(animations[1].effect.timing.duration, 2750); + + assert_equals(animations[2].currentTime, 3000); + assert_equals(animations[2].effect.timing.duration, 3750); +}, 'Multiple same animation names should persist with animation timing updates.'); + +test(() => { + clearAnimations(); + + setAnimationProperty('a 1500ms paused, a 2500ms paused, b 3500ms paused, b 4500ms paused'); + var animations = getAnimations(); + assert_equals(animations.length, 4); + animations[0].currentTime = 1000; + animations[1].currentTime = 2000; + animations[2].currentTime = 3000; + animations[3].currentTime = 4000; + + setAnimationProperty('a 1500ms paused, b 3500ms paused, a 2500ms paused, b 4500ms paused'); + animations = getAnimations(); + assert_equals(animations.length, 4); + + assert_equals(animations[0].currentTime, 1000); + assert_equals(animations[0].effect.timing.duration, 1500); + + assert_equals(animations[1].currentTime, 2000); + assert_equals(animations[1].effect.timing.duration, 2500); + + assert_equals(animations[2].currentTime, 3000); + assert_equals(animations[2].effect.timing.duration, 3500); + + assert_equals(animations[3].currentTime, 4000); + assert_equals(animations[3].effect.timing.duration, 4500); +}, 'Mixed multiple same animation names should persist based on their same name relative position'); + +test(() => { + clearAnimations(); + + setAnimationProperty('a 1500ms paused, a 2500ms paused, a 3500ms paused'); + var animations = getAnimations(); + assert_equals(animations.length, 3); + animations[0].currentTime = 1000; + animations[1].currentTime = 2000; + animations[2].currentTime = 3000; + + setAnimationProperty('a 1500ms paused, b 2500ms paused, a 3500ms paused'); + animations = getAnimations(); + assert_equals(animations.length, 3); + + assert_equals(animations[0].currentTime, 1000); + assert_equals(animations[0].effect.timing.duration, 1500); + + assert_equals(animations[1].currentTime, 2000); + assert_equals(animations[1].effect.timing.duration, 3500); + + assert_equals(animations[2].currentTime, null); + assert_equals(animations[2].effect.timing.duration, 2500); +}, 'Removing same animation names should cancel animations from the end of the name list.'); + +test(() => { + clearAnimations(); + + setAnimationProperty('a 1500ms paused, a 2500ms paused'); + var animations = getAnimations(); + assert_equals(animations.length, 2); + animations[0].currentTime = 1000; + animations[1].currentTime = 2000; + + setAnimationProperty('a 3500ms paused, a 2500ms paused, a 1500ms paused'); + animations = getAnimations(); + assert_equals(animations.length, 3); + + assert_equals(animations[0].currentTime, 1000); + assert_equals(animations[0].effect.timing.duration, 3500); + + assert_equals(animations[1].currentTime, 2000); + assert_equals(animations[1].effect.timing.duration, 2500); + + assert_equals(animations[2].currentTime, null); + assert_equals(animations[2].effect.timing.duration, 1500); +}, 'Adding same animation names should start additional animations from the end of the name list.'); +</script> diff --git a/third_party/WebKit/Source/core/animation/css/CSSAnimationUpdate.h b/third_party/WebKit/Source/core/animation/css/CSSAnimationUpdate.h index a45b0a9..5131ac4 100644 --- a/third_party/WebKit/Source/core/animation/css/CSSAnimationUpdate.h +++ b/third_party/WebKit/Source/core/animation/css/CSSAnimationUpdate.h @@ -36,8 +36,9 @@ public: { } - NewAnimation(AtomicString name, InertEffect* effect, Timing timing, PassRefPtrWillBeRawPtr<StyleRuleKeyframes> styleRule) + NewAnimation(AtomicString name, size_t nameIndex, InertEffect* effect, Timing timing, PassRefPtrWillBeRawPtr<StyleRuleKeyframes> styleRule) : name(name) + , nameIndex(nameIndex) , effect(effect) , timing(timing) , styleRule(styleRule) @@ -52,6 +53,7 @@ public: } AtomicString name; + size_t nameIndex; Member<InertEffect> effect; Timing timing; RefPtrWillBeMember<StyleRuleKeyframes> styleRule; @@ -66,8 +68,8 @@ public: { } - UpdatedAnimation(AtomicString name, Animation* animation, InertEffect* effect, Timing specifiedTiming, PassRefPtrWillBeRawPtr<StyleRuleKeyframes> styleRule) - : name(name) + UpdatedAnimation(size_t index, Animation* animation, InertEffect* effect, Timing specifiedTiming, PassRefPtrWillBeRawPtr<StyleRuleKeyframes> styleRule) + : index(index) , animation(animation) , effect(effect) , specifiedTiming(specifiedTiming) @@ -83,7 +85,7 @@ public: visitor->trace(styleRule); } - AtomicString name; + size_t index; Member<Animation> animation; Member<InertEffect> effect; Timing specifiedTiming; @@ -110,8 +112,8 @@ public: m_newTransitions = update.newTransitions(); m_activeInterpolationsForAnimations = update.activeInterpolationsForAnimations(); m_activeInterpolationsForTransitions = update.activeInterpolationsForTransitions(); - m_cancelledAnimationNames = update.cancelledAnimationNames(); - m_animationsWithPauseToggled = update.animationsWithPauseToggled(); + m_cancelledAnimationIndices = update.cancelledAnimationIndices(); + m_animationIndicesWithPauseToggled = update.animationIndicesWithPauseToggled(); m_cancelledTransitions = update.cancelledTransitions(); m_finishedTransitions = update.finishedTransitions(); m_updatedCompositorKeyframes = update.updatedCompositorKeyframes(); @@ -124,33 +126,33 @@ public: m_newTransitions.clear(); m_activeInterpolationsForAnimations.clear(); m_activeInterpolationsForTransitions.clear(); - m_cancelledAnimationNames.clear(); - m_animationsWithPauseToggled.clear(); + m_cancelledAnimationIndices.clear(); + m_animationIndicesWithPauseToggled.clear(); m_cancelledTransitions.clear(); m_finishedTransitions.clear(); m_updatedCompositorKeyframes.clear(); } - void startAnimation(const AtomicString& animationName, InertEffect* effect, const Timing& timing, PassRefPtrWillBeRawPtr<StyleRuleKeyframes> styleRule) + void startAnimation(const AtomicString& animationName, size_t nameIndex, InertEffect* effect, const Timing& timing, PassRefPtrWillBeRawPtr<StyleRuleKeyframes> styleRule) { effect->setName(animationName); - m_newAnimations.append(NewAnimation(animationName, effect, timing, styleRule)); + m_newAnimations.append(NewAnimation(animationName, nameIndex, effect, timing, styleRule)); } // Returns whether animation has been suppressed and should be filtered during style application. bool isSuppressedAnimation(const Animation* animation) const { return m_suppressedAnimations.contains(animation); } - void cancelAnimation(const AtomicString& name, Animation& animation) + void cancelAnimation(size_t index, const Animation& animation) { - m_cancelledAnimationNames.append(name); + m_cancelledAnimationIndices.append(index); m_suppressedAnimations.add(&animation); } - void toggleAnimationPaused(const AtomicString& name) + void toggleAnimationIndexPaused(size_t index) { - m_animationsWithPauseToggled.append(name); + m_animationIndicesWithPauseToggled.append(index); } - void updateAnimation(const AtomicString& name, Animation* animation, InertEffect* effect, const Timing& specifiedTiming, + void updateAnimation(size_t index, Animation* animation, InertEffect* effect, const Timing& specifiedTiming, PassRefPtrWillBeRawPtr<StyleRuleKeyframes> styleRule) { - m_animationsWithUpdates.append(UpdatedAnimation(name, animation, effect, specifiedTiming, styleRule)); + m_animationsWithUpdates.append(UpdatedAnimation(index, animation, effect, specifiedTiming, styleRule)); m_suppressedAnimations.add(animation); } void updateCompositorKeyframes(Animation* animation) @@ -173,9 +175,9 @@ public: void finishTransition(CSSPropertyID id) { m_finishedTransitions.add(id); } const HeapVector<NewAnimation>& newAnimations() const { return m_newAnimations; } - const Vector<AtomicString>& cancelledAnimationNames() const { return m_cancelledAnimationNames; } + const Vector<size_t>& cancelledAnimationIndices() const { return m_cancelledAnimationIndices; } const HeapHashSet<Member<const Animation>>& suppressedAnimations() const { return m_suppressedAnimations; } - const Vector<AtomicString>& animationsWithPauseToggled() const { return m_animationsWithPauseToggled; } + const Vector<size_t>& animationIndicesWithPauseToggled() const { return m_animationIndicesWithPauseToggled; } const HeapVector<UpdatedAnimation>& animationsWithUpdates() const { return m_animationsWithUpdates; } const HeapVector<Member<Animation>>& updatedCompositorKeyframes() const { return m_updatedCompositorKeyframes; } @@ -206,9 +208,9 @@ public: bool isEmpty() const { return m_newAnimations.isEmpty() - && m_cancelledAnimationNames.isEmpty() + && m_cancelledAnimationIndices.isEmpty() && m_suppressedAnimations.isEmpty() - && m_animationsWithPauseToggled.isEmpty() + && m_animationIndicesWithPauseToggled.isEmpty() && m_animationsWithUpdates.isEmpty() && m_newTransitions.isEmpty() && m_cancelledTransitions.isEmpty() @@ -233,9 +235,9 @@ private: // with the same name, due to the way in which we split up animations with // incomplete keyframes. HeapVector<NewAnimation> m_newAnimations; - Vector<AtomicString> m_cancelledAnimationNames; + Vector<size_t> m_cancelledAnimationIndices; HeapHashSet<Member<const Animation>> m_suppressedAnimations; - Vector<AtomicString> m_animationsWithPauseToggled; + Vector<size_t> m_animationIndicesWithPauseToggled; HeapVector<UpdatedAnimation> m_animationsWithUpdates; HeapVector<Member<Animation>> m_updatedCompositorKeyframes; diff --git a/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp b/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp index 13865e9..4070218 100644 --- a/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp +++ b/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp @@ -191,8 +191,8 @@ CSSAnimations::CSSAnimations() bool CSSAnimations::isAnimationForInspector(const Animation& animation) { - for (const auto& it : m_animations) { - if (it.value->animation->sequenceNumber() == animation.sequenceNumber()) + for (const auto& runningAnimation : m_runningAnimations) { + if (runningAnimation->animation->sequenceNumber() == animation.sequenceNumber()) return true; } return false; @@ -232,7 +232,7 @@ void CSSAnimations::calculateCompositorAnimationUpdate(CSSAnimationUpdate& updat return; CSSAnimations& cssAnimations = elementAnimations->cssAnimations(); - for (auto& runningAnimation : cssAnimations.m_animations.values()) { + for (auto& runningAnimation : cssAnimations.m_runningAnimations) { Animation& animation = *runningAnimation->animation; if (animation.effect() && animation.effect()->isKeyframeEffect()) { EffectModel* model = toKeyframeEffect(animation.effect())->model(); @@ -276,18 +276,24 @@ void CSSAnimations::calculateAnimationUpdate(CSSAnimationUpdate& update, const E const CSSAnimations* cssAnimations = elementAnimations ? &elementAnimations->cssAnimations() : nullptr; const Element* elementForScoping = animatingElement ? animatingElement : &element; - HashSet<AtomicString> inactive; - if (cssAnimations) { - for (const auto& entry : cssAnimations->m_animations) - inactive.add(entry.key); - } + Vector<bool> cancelRunningAnimationFlags(cssAnimations ? cssAnimations->m_runningAnimations.size() : 0); + for (bool& flag : cancelRunningAnimationFlags) + flag = true; - if (style.display() != NONE) { - for (size_t i = 0; animationData && i < animationData->nameList().size(); ++i) { - AtomicString animationName(animationData->nameList()[i]); - if (animationName == CSSAnimationData::initialName()) + if (animationData && style.display() != NONE) { + const Vector<AtomicString>& nameList = animationData->nameList(); + for (size_t i = 0; i < nameList.size(); ++i) { + AtomicString name = nameList[i]; + if (name == CSSAnimationData::initialName()) continue; + // Find n where this is the nth occurence of this animation name. + size_t nameIndex = 0; + for (size_t j = 0; j < i; j++) { + if (nameList[j] == name) + nameIndex++; + } + const bool isPaused = CSSTimingData::getRepeated(animationData->playStateList(), i) == AnimPlayStatePaused; Timing timing = animationData->convertToTiming(i); @@ -295,45 +301,54 @@ void CSSAnimations::calculateAnimationUpdate(CSSAnimationUpdate& update, const E RefPtr<TimingFunction> keyframeTimingFunction = timing.timingFunction; timing.timingFunction = Timing::defaults().timingFunction; - RefPtrWillBeRawPtr<StyleRuleKeyframes> keyframesRule = resolver->findKeyframesRule(elementForScoping, animationName); + RefPtrWillBeRawPtr<StyleRuleKeyframes> keyframesRule = resolver->findKeyframesRule(elementForScoping, name); if (!keyframesRule) continue; // Cancel the animation if there's no style rule for it. + const RunningAnimation* existingAnimation = nullptr; + size_t existingAnimationIndex = 0; + if (cssAnimations) { - AnimationMap::const_iterator existing(cssAnimations->m_animations.find(animationName)); - if (existing != cssAnimations->m_animations.end()) { - inactive.remove(animationName); - - const RunningAnimation* runningAnimation = existing->value.get(); - Animation* animation = runningAnimation->animation.get(); - - if (keyframesRule != runningAnimation->styleRule || keyframesRule->version() != runningAnimation->styleRuleVersion || runningAnimation->specifiedTiming != specifiedTiming) { - ASSERT(!isAnimationStyleChange); - update.updateAnimation(animationName, animation, InertEffect::create( - createKeyframeEffectModel(resolver, animatingElement, element, &style, parentStyle, animationName, keyframeTimingFunction.get(), i), - timing, isPaused, animation->unlimitedCurrentTimeInternal()), specifiedTiming, keyframesRule); + for (size_t i = 0; i < cssAnimations->m_runningAnimations.size(); i++) { + const RunningAnimation& runningAnimation = *cssAnimations->m_runningAnimations[i]; + if (runningAnimation.name == name && runningAnimation.nameIndex == nameIndex) { + existingAnimation = &runningAnimation; + existingAnimationIndex = i; + break; } + } + } - if (isPaused != animation->paused()) { - ASSERT(!isAnimationStyleChange); - update.toggleAnimationPaused(animationName); - } + if (existingAnimation) { + cancelRunningAnimationFlags[existingAnimationIndex] = false; + + Animation* animation = existingAnimation->animation.get(); - continue; + if (keyframesRule != existingAnimation->styleRule || keyframesRule->version() != existingAnimation->styleRuleVersion || existingAnimation->specifiedTiming != specifiedTiming) { + ASSERT(!isAnimationStyleChange); + update.updateAnimation(existingAnimationIndex, animation, InertEffect::create( + createKeyframeEffectModel(resolver, animatingElement, element, &style, parentStyle, name, keyframeTimingFunction.get(), i), + timing, isPaused, animation->unlimitedCurrentTimeInternal()), specifiedTiming, keyframesRule); } - } - ASSERT(!isAnimationStyleChange); - update.startAnimation(animationName, InertEffect::create( - createKeyframeEffectModel(resolver, animatingElement, element, &style, parentStyle, animationName, keyframeTimingFunction.get(), i), - timing, isPaused, 0), specifiedTiming, keyframesRule); + if (isPaused != animation->paused()) { + ASSERT(!isAnimationStyleChange); + update.toggleAnimationIndexPaused(existingAnimationIndex); + } + } else { + ASSERT(!isAnimationStyleChange); + update.startAnimation(name, nameIndex, InertEffect::create( + createKeyframeEffectModel(resolver, animatingElement, element, &style, parentStyle, name, keyframeTimingFunction.get(), i), + timing, isPaused, 0), specifiedTiming, keyframesRule); + } } } - ASSERT(inactive.isEmpty() || cssAnimations); - for (const AtomicString& animationName : inactive) { - ASSERT(!isAnimationStyleChange); - update.cancelAnimation(animationName, *cssAnimations->m_animations.get(animationName)->animation); + for (size_t i = 0; i < cancelRunningAnimationFlags.size(); i++) { + if (cancelRunningAnimationFlags[i]) { + ASSERT(cssAnimations && !isAnimationStyleChange); + update.cancelAnimation(i, *cssAnimations->m_runningAnimations[i]->animation); + } } } @@ -350,20 +365,23 @@ void CSSAnimations::maybeApplyPendingUpdate(Element* element) // https://code.google.com/p/chromium/issues/detail?id=339847 DisableCompositingQueryAsserts disabler; - for (const AtomicString& animationName : m_pendingUpdate.cancelledAnimationNames()) { - Animation* animation = m_animations.take(animationName)->animation; - animation->cancel(); - animation->update(TimingUpdateOnDemand); + const Vector<size_t>& cancelledIndices = m_pendingUpdate.cancelledAnimationIndices(); + for (size_t i = cancelledIndices.size(); i-- > 0;) { + ASSERT(i == cancelledIndices.size() - 1 || cancelledIndices[i] < cancelledIndices[i + 1]); + Animation& animation = *m_runningAnimations[cancelledIndices[i]]->animation; + animation.cancel(); + animation.update(TimingUpdateOnDemand); + m_runningAnimations.remove(cancelledIndices[i]); } - for (const AtomicString& animationName : m_pendingUpdate.animationsWithPauseToggled()) { - Animation* animation = m_animations.get(animationName)->animation.get(); - if (animation->paused()) - animation->unpause(); + for (size_t pausedIndex : m_pendingUpdate.animationIndicesWithPauseToggled()) { + Animation& animation = *m_runningAnimations[pausedIndex]->animation; + if (animation.paused()) + animation.unpause(); else - animation->pause(); - if (animation->outdated()) - animation->update(TimingUpdateOnDemand); + animation.pause(); + if (animation.outdated()) + animation.update(TimingUpdateOnDemand); } for (const auto& animation : m_pendingUpdate.updatedCompositorKeyframes()) @@ -375,7 +393,7 @@ void CSSAnimations::maybeApplyPendingUpdate(Element* element) effect->setModel(entry.effect->model()); effect->updateSpecifiedTiming(entry.effect->specifiedTiming()); - m_animations.find(entry.name)->value->update(entry); + m_runningAnimations[entry.index]->update(entry); } for (const auto& entry : m_pendingUpdate.newAnimations()) { @@ -388,7 +406,7 @@ void CSSAnimations::maybeApplyPendingUpdate(Element* element) animation->pause(); animation->update(TimingUpdateOnDemand); - m_animations.set(entry.name, new RunningAnimation(animation, entry)); + m_runningAnimations.append(new RunningAnimation(animation, entry)); } // Transitions that are run on the compositor only update main-thread state @@ -613,9 +631,9 @@ void CSSAnimations::calculateTransitionUpdate(CSSAnimationUpdate& update, const void CSSAnimations::cancel() { - for (const auto& entry : m_animations) { - entry.value->animation->cancel(); - entry.value->animation->update(TimingUpdateOnDemand); + for (const auto& runningAnimation : m_runningAnimations) { + runningAnimation->animation->cancel(); + runningAnimation->animation->update(TimingUpdateOnDemand); } for (const auto& entry : m_transitions) { @@ -623,7 +641,7 @@ void CSSAnimations::cancel() entry.value.animation->update(TimingUpdateOnDemand); } - m_animations.clear(); + m_runningAnimations.clear(); m_transitions.clear(); clearPendingUpdate(); } @@ -818,7 +836,7 @@ DEFINE_TRACE(CSSAnimations) { visitor->trace(m_transitions); visitor->trace(m_pendingUpdate); - visitor->trace(m_animations); + visitor->trace(m_runningAnimations); } } // namespace blink diff --git a/third_party/WebKit/Source/core/animation/css/CSSAnimations.h b/third_party/WebKit/Source/core/animation/css/CSSAnimations.h index b28a7e1..70437b7 100644 --- a/third_party/WebKit/Source/core/animation/css/CSSAnimations.h +++ b/third_party/WebKit/Source/core/animation/css/CSSAnimations.h @@ -73,7 +73,7 @@ public: m_pendingUpdate.clear(); } void maybeApplyPendingUpdate(Element*); - bool isEmpty() const { return m_animations.isEmpty() && m_transitions.isEmpty() && m_pendingUpdate.isEmpty(); } + bool isEmpty() const { return m_runningAnimations.isEmpty() && m_transitions.isEmpty() && m_pendingUpdate.isEmpty(); } void cancel(); DECLARE_TRACE(); @@ -83,6 +83,8 @@ private: public: RunningAnimation(Animation* animation, CSSAnimationUpdate::NewAnimation newAnimation) : animation(animation) + , name(newAnimation.name) + , nameIndex(newAnimation.nameIndex) , specifiedTiming(newAnimation.timing) , styleRule(newAnimation.styleRule) , styleRuleVersion(newAnimation.styleRuleVersion) @@ -91,6 +93,7 @@ private: void update(CSSAnimationUpdate::UpdatedAnimation update) { + ASSERT(update.animation == animation); styleRule = update.styleRule; styleRuleVersion = update.styleRuleVersion; specifiedTiming = update.specifiedTiming; @@ -103,6 +106,8 @@ private: } Member<Animation> animation; + AtomicString name; + size_t nameIndex; Timing specifiedTiming; RefPtrWillBeMember<StyleRuleKeyframes> styleRule; unsigned styleRuleVersion; @@ -121,8 +126,7 @@ private: const AnimatableValue* to; }; - using AnimationMap = HeapHashMap<AtomicString, Member<RunningAnimation>>; - AnimationMap m_animations; + HeapVector<Member<RunningAnimation>> m_runningAnimations; using TransitionMap = HeapHashMap<CSSPropertyID, RunningTransition>; TransitionMap m_transitions; |