summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--third_party/WebKit/LayoutTests/animations/multiple-same-animations-asan-crash.html2
-rw-r--r--third_party/WebKit/LayoutTests/animations/multiple-same-name-css-animations.html139
-rw-r--r--third_party/WebKit/Source/core/animation/css/CSSAnimationUpdate.h46
-rw-r--r--third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp132
-rw-r--r--third_party/WebKit/Source/core/animation/css/CSSAnimations.h10
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;