Changeset 252911 in webkit


Ignore:
Timestamp:
Nov 27, 2019 11:38:43 AM (4 years ago)
Author:
graouts@webkit.org
Message:

REGRESSION(r252455): imported/w3c/web-platform-tests/dom/events/Event-dispatch-on-disabled-elements.html fails on iOS and WK1
https://bugs.webkit.org/show_bug.cgi?id=204272
<rdar://problem/57253742>

Reviewed by Dean Jackson.

Source/WebCore:

Events for declarative animations are dispatched using a MainThreadGenericEventQueue which dispatches enqueued events asynchronously. When a declarative
animation would be canceled, AnimationTimeline::cancelDeclarativeAnimation() would be called and would enqueue a "transitioncancel" or "animationcancel"
event (depending on the animation type) by virtue of calling DeclarativeAnimation::cancelFromStyle(), and would also call AnimationTimeline::removeAnimation()
right after. However, calling AnimationTimeline::removeAnimation() could have the side effect of removing the last reference to the DeclarativeAnimation
object, which would destroy its attached MainThreadGenericEventQueue before it had the time to dispatch the queued "transitioncancel" or "animationcancel"
event.

The call to AnimationTimeline::removeAnimation() in AnimationTimeline::cancelDeclarativeAnimation() is actually unnecessary. Simply canceling the animation
via DeclarativeAnimation::cancelFromStyle() will end up calling AnimationTimeline::removeAnimation() the next time animations are updated, which will leave
time for the cancel events to be dispatched. So all we need to do is remove AnimationTimeline::cancelDeclarativeAnimation() and replace its call sites with
simple calls to DeclarativeAnimation::cancelFromStyle().

Making this change broke a test however: imported/w3c/web-platform-tests/css/css-animations/Document-getAnimations.tentative.html. We actually passed that
test by chance without implementing the feature required to make it work. We now implement the correct way to track a global position for an animation by
only setting one for declarative animations once they are disassociated with their owning element and have a non-idle play state.

And a few other tests broke: animations/animation-shorthand-name-order.html, imported/w3c/web-platform-tests/css/css-animations/animationevent-types.html
and webanimations/css-animations.html. The reason for those tests being broken was that not calling AnimationTimeline::removeAnimation() instantly as CSS
Animations were canceled also meant that the KeyframeEffectStack for the targeted element wasn't updated. To solve this, we added the animationTimingDidChange()
method on KeyframeEffect which is called whenever timing on the owning Animation changes, so for instance when cancel() is called as we cancel a CSS
Animation. That way we ensure we add and remove KeyframeEffect instances from the KeyframeEffectStack as the animation becomes relevant, which is now
an added condition checked by KeyframeEffectStack::addEffect().

Finally, this revealed an issue in KeyframeEffectStack::ensureEffectsAreSorted() where we would consider CSSTransition and CSSAnimation objects to be
representative of a CSS Transition or CSS Animation even after the relationship with their owning element had been severed. We now correctly check that
relationship is intact and otherwise consider those animations just like any other animation.

  • animation/AnimationTimeline.cpp:

(WebCore::AnimationTimeline::animationTimingDidChange):
(WebCore::AnimationTimeline::updateGlobalPosition):
(WebCore::AnimationTimeline::removeDeclarativeAnimationFromListsForOwningElement):
(WebCore::AnimationTimeline::updateCSSAnimationsForElement):
(WebCore::AnimationTimeline::updateCSSTransitionsForElementAndProperty):
(WebCore::AnimationTimeline::updateCSSTransitionsForElement):
(WebCore::AnimationTimeline::cancelDeclarativeAnimation): Deleted.

  • animation/AnimationTimeline.h:
  • animation/CSSAnimation.cpp:

(WebCore::CSSAnimation::syncPropertiesWithBackingAnimation):

  • animation/CSSTransition.cpp:

(WebCore::CSSTransition::setTimingProperties):

  • animation/DeclarativeAnimation.cpp:

(WebCore::DeclarativeAnimation::canHaveGlobalPosition):

  • animation/DeclarativeAnimation.h:
  • animation/DocumentTimeline.cpp:

(WebCore::DocumentTimeline::getAnimations const):

  • animation/KeyframeEffect.cpp:

(WebCore::KeyframeEffect::animationTimelineDidChange):
(WebCore::KeyframeEffect::animationTimingDidChange):
(WebCore::KeyframeEffect::updateEffectStackMembership):
(WebCore::KeyframeEffect::setAnimation):
(WebCore::KeyframeEffect::setTarget):

  • animation/KeyframeEffect.h:
  • animation/KeyframeEffectStack.cpp:

(WebCore::KeyframeEffectStack::addEffect):
(WebCore::KeyframeEffectStack::ensureEffectsAreSorted):

  • animation/KeyframeEffectStack.h:
  • animation/WebAnimation.cpp:

(WebCore::WebAnimation::timingDidChange):

  • animation/WebAnimation.h:

(WebCore::WebAnimation::canHaveGlobalPosition):

LayoutTests:

Removing this specific expectation for WK1 since it now behaves just like the other configurations.

  • platform/mac-wk1/imported/w3c/web-platform-tests/dom/events/Event-dispatch-on-disabled-elements-expected.txt: Removed.
Location:
trunk
Files:
1 deleted
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r252910 r252911  
     12019-11-27  Antoine Quint  <graouts@apple.com>
     2
     3        REGRESSION(r252455): imported/w3c/web-platform-tests/dom/events/Event-dispatch-on-disabled-elements.html fails on iOS and WK1
     4        https://bugs.webkit.org/show_bug.cgi?id=204272
     5        <rdar://problem/57253742>
     6
     7        Reviewed by Dean Jackson.
     8
     9        Removing this specific expectation for WK1 since it now behaves just like the other configurations.
     10
     11        * platform/mac-wk1/imported/w3c/web-platform-tests/dom/events/Event-dispatch-on-disabled-elements-expected.txt: Removed.
     12
    1132019-11-27  Jonathan Bedard  <jbedard@apple.com>
    214
  • trunk/Source/WebCore/ChangeLog

    r252909 r252911  
     12019-11-27  Antoine Quint  <graouts@apple.com>
     2
     3        REGRESSION(r252455): imported/w3c/web-platform-tests/dom/events/Event-dispatch-on-disabled-elements.html fails on iOS and WK1
     4        https://bugs.webkit.org/show_bug.cgi?id=204272
     5        <rdar://problem/57253742>
     6
     7        Reviewed by Dean Jackson.
     8
     9        Events for declarative animations are dispatched using a MainThreadGenericEventQueue which dispatches enqueued events asynchronously. When a declarative
     10        animation would be canceled, AnimationTimeline::cancelDeclarativeAnimation() would be called and would enqueue a "transitioncancel" or "animationcancel"
     11        event (depending on the animation type) by virtue of calling DeclarativeAnimation::cancelFromStyle(), and would also call AnimationTimeline::removeAnimation()
     12        right after. However, calling AnimationTimeline::removeAnimation() could have the side effect of removing the last reference to the DeclarativeAnimation
     13        object, which would destroy its attached MainThreadGenericEventQueue before it had the time to dispatch the queued "transitioncancel" or "animationcancel"
     14        event.
     15
     16        The call to AnimationTimeline::removeAnimation() in AnimationTimeline::cancelDeclarativeAnimation() is actually unnecessary. Simply canceling the animation
     17        via DeclarativeAnimation::cancelFromStyle() will end up calling AnimationTimeline::removeAnimation() the next time animations are updated, which will leave
     18        time for the cancel events to be dispatched. So all we need to do is remove AnimationTimeline::cancelDeclarativeAnimation() and replace its call sites with
     19        simple calls to DeclarativeAnimation::cancelFromStyle().
     20
     21        Making this change broke a test however: imported/w3c/web-platform-tests/css/css-animations/Document-getAnimations.tentative.html. We actually passed that
     22        test by chance without implementing the feature required to make it work. We now implement the correct way to track a global position for an animation by
     23        only setting one for declarative animations once they are disassociated with their owning element and have a non-idle play state.
     24
     25        And a few other tests broke: animations/animation-shorthand-name-order.html, imported/w3c/web-platform-tests/css/css-animations/animationevent-types.html
     26        and webanimations/css-animations.html. The reason for those tests being broken was that not calling AnimationTimeline::removeAnimation() instantly as CSS
     27        Animations were canceled also meant that the KeyframeEffectStack for the targeted element wasn't updated. To solve this, we added the animationTimingDidChange()
     28        method on KeyframeEffect which is called whenever timing on the owning Animation changes, so for instance when cancel() is called as we cancel a CSS
     29        Animation. That way we ensure we add and remove KeyframeEffect instances from the KeyframeEffectStack as the animation becomes relevant, which is now
     30        an added condition checked by KeyframeEffectStack::addEffect().
     31
     32        Finally, this revealed an issue in KeyframeEffectStack::ensureEffectsAreSorted() where we would consider CSSTransition and CSSAnimation objects to be
     33        representative of a CSS Transition or CSS Animation even after the relationship with their owning element had been severed. We now correctly check that
     34        relationship is intact and otherwise consider those animations just like any other animation.
     35
     36        * animation/AnimationTimeline.cpp:
     37        (WebCore::AnimationTimeline::animationTimingDidChange):
     38        (WebCore::AnimationTimeline::updateGlobalPosition):
     39        (WebCore::AnimationTimeline::removeDeclarativeAnimationFromListsForOwningElement):
     40        (WebCore::AnimationTimeline::updateCSSAnimationsForElement):
     41        (WebCore::AnimationTimeline::updateCSSTransitionsForElementAndProperty):
     42        (WebCore::AnimationTimeline::updateCSSTransitionsForElement):
     43        (WebCore::AnimationTimeline::cancelDeclarativeAnimation): Deleted.
     44        * animation/AnimationTimeline.h:
     45        * animation/CSSAnimation.cpp:
     46        (WebCore::CSSAnimation::syncPropertiesWithBackingAnimation):
     47        * animation/CSSTransition.cpp:
     48        (WebCore::CSSTransition::setTimingProperties):
     49        * animation/DeclarativeAnimation.cpp:
     50        (WebCore::DeclarativeAnimation::canHaveGlobalPosition):
     51        * animation/DeclarativeAnimation.h:
     52        * animation/DocumentTimeline.cpp:
     53        (WebCore::DocumentTimeline::getAnimations const):
     54        * animation/KeyframeEffect.cpp:
     55        (WebCore::KeyframeEffect::animationTimelineDidChange):
     56        (WebCore::KeyframeEffect::animationTimingDidChange):
     57        (WebCore::KeyframeEffect::updateEffectStackMembership):
     58        (WebCore::KeyframeEffect::setAnimation):
     59        (WebCore::KeyframeEffect::setTarget):
     60        * animation/KeyframeEffect.h:
     61        * animation/KeyframeEffectStack.cpp:
     62        (WebCore::KeyframeEffectStack::addEffect):
     63        (WebCore::KeyframeEffectStack::ensureEffectsAreSorted):
     64        * animation/KeyframeEffectStack.h:
     65        * animation/WebAnimation.cpp:
     66        (WebCore::WebAnimation::timingDidChange):
     67        * animation/WebAnimation.h:
     68        (WebCore::WebAnimation::canHaveGlobalPosition):
     69
    1702019-11-27  James Darpinian  <jdarpinian@chromium.org>
    271
  • trunk/Source/WebCore/animation/AnimationTimeline.cpp

    r252527 r252911  
    6363void AnimationTimeline::animationTimingDidChange(WebAnimation& animation)
    6464{
     65    updateGlobalPosition(animation);
     66
    6567    if (m_animations.add(&animation)) {
    66         animation.setGlobalPosition(m_allAnimations.size());
    6768        m_allAnimations.append(makeWeakPtr(&animation));
    6869        auto* timeline = animation.timeline();
     
    7071            timeline->removeAnimation(animation);
    7172    }
     73}
     74
     75void AnimationTimeline::updateGlobalPosition(WebAnimation& animation)
     76{
     77    static uint64_t s_globalPosition = 0;
     78    if (!animation.globalPosition() && animation.canHaveGlobalPosition())
     79        animation.setGlobalPosition(++s_globalPosition);
    7280}
    7381
     
    157165            auto& cssAnimationsByName = iterator->value;
    158166            auto& name = downcast<CSSAnimation>(animation).animationName();
    159             cssAnimationsByName.remove(name);
    160             if (cssAnimationsByName.isEmpty())
    161                 m_elementToCSSAnimationByName.remove(&element);
     167            if (cssAnimationsByName.get(name) == &animation) {
     168                cssAnimationsByName.remove(name);
     169                if (cssAnimationsByName.isEmpty())
     170                    m_elementToCSSAnimationByName.remove(&element);
     171            }
    162172        }
    163173    } else if (is<CSSTransition>(animation)) {
     
    253263        if (m_elementToCSSAnimationByName.contains(&element)) {
    254264            for (const auto& cssAnimationsByNameMapItem : m_elementToCSSAnimationByName.take(&element))
    255                 cancelDeclarativeAnimation(*cssAnimationsByNameMapItem.value);
     265                cssAnimationsByNameMapItem.value->cancelFromStyle();
    256266        }
    257267        element.ensureKeyframeEffectStack().setCSSAnimationNames(WTFMove(animationNames));
     
    282292            auto& currentAnimation = currentAnimations->animation(i);
    283293            auto& name = currentAnimation.name();
    284             animationNames.append(name);
    285294            if (namesOfPreviousAnimations.contains(name)) {
    286295                // We've found the name of this animation in our list of previous animations, this means we've already
     
    289298                if (auto cssAnimation = cssAnimationsByName.get(name))
    290299                    cssAnimation->setBackingAnimation(currentAnimation);
     300                animationNames.append(name);
    291301            } else if (shouldConsiderAnimation(element, currentAnimation)) {
    292302                // Otherwise we are dealing with a new animation name and must create a CSSAnimation for it.
    293303                cssAnimationsByName.set(name, CSSAnimation::create(element, currentAnimation, currentStyle, afterChangeStyle));
     304                animationNames.append(name);
    294305            }
    295306            // Remove the name of this animation from our list since it's now known to be current.
     
    302313    for (const auto& nameOfAnimationToRemove : namesOfPreviousAnimations) {
    303314        if (auto animation = cssAnimationsByName.take(nameOfAnimationToRemove))
    304             cancelDeclarativeAnimation(*animation);
     315            animation->cancelFromStyle();
    305316    }
    306317
     
    473484            // 1. If the current value of the property in the running transition is equal to the value of the property in the after-change style,
    474485            //    or if these two values cannot be interpolated, then implementations must cancel the running transition.
    475             cancelDeclarativeAnimation(*previouslyRunningTransition);
     486            previouslyRunningTransition->cancelFromStyle();
    476487        } else if (transitionCombinedDuration(matchingBackingAnimation) <= 0.0 || !CSSPropertyAnimation::canPropertyBeInterpolated(property, &previouslyRunningTransitionCurrentStyle, &afterChangeStyle)) {
    477488            // 2. Otherwise, if the combined duration is less than or equal to 0s, or if the current value of the property in the running transition
    478489            //    cannot be interpolated with the value of the property in the after-change style, then implementations must cancel the running transition.
    479             cancelDeclarativeAnimation(*previouslyRunningTransition);
     490            previouslyRunningTransition->cancelFromStyle();
    480491        } else if (CSSPropertyAnimation::propertiesEqual(property, &previouslyRunningTransition->reversingAdjustedStartStyle(), &afterChangeStyle)) {
    481492            // 3. Otherwise, if the reversing-adjusted start value of the running transition is the same as the value of the property in the after-change
    482493            //    style (see the section on reversing of transitions for why these case exists), implementations must cancel the running transition
    483             cancelDeclarativeAnimation(*previouslyRunningTransition);
     494            previouslyRunningTransition->cancelFromStyle();
    484495
    485496            // and start a new transition whose:
     
    507518        } else {
    508519            // 4. Otherwise, implementations must cancel the running transition
    509             cancelDeclarativeAnimation(*previouslyRunningTransition);
     520            previouslyRunningTransition->cancelFromStyle();
    510521
    511522            // and start a new transition whose:
     
    531542        if (m_elementToRunningCSSTransitionByCSSPropertyID.contains(&element)) {
    532543            for (const auto& cssTransitionsByCSSPropertyIDMapItem : m_elementToRunningCSSTransitionByCSSPropertyID.take(&element))
    533                 cancelDeclarativeAnimation(*cssTransitionsByCSSPropertyIDMapItem.value);
     544                cssTransitionsByCSSPropertyIDMapItem.value->cancelFromStyle();
    534545        }
    535546        return;
     
    569580}
    570581
    571 void AnimationTimeline::cancelDeclarativeAnimation(DeclarativeAnimation& animation)
    572 {
    573     animation.cancelFromStyle();
    574     removeAnimation(animation);
    575     m_allAnimations.removeFirst(&animation);
    576 }
    577 
    578582} // namespace WebCore
  • trunk/Source/WebCore/animation/AnimationTimeline.h

    r251543 r252911  
    8383
    8484private:
     85    void updateGlobalPosition(WebAnimation&);
    8586    RefPtr<WebAnimation> cssAnimationForElementAndProperty(Element&, CSSPropertyID);
    8687    PropertyToTransitionMap& ensureRunningTransitionsByProperty(Element&);
    8788    void updateCSSTransitionsForElementAndProperty(Element&, CSSPropertyID, const RenderStyle& currentStyle, const RenderStyle& afterChangeStyle, PropertyToTransitionMap&, PropertyToTransitionMap&, const MonotonicTime);
    88     void cancelDeclarativeAnimation(DeclarativeAnimation&);
    8989
    9090    ElementToAnimationsMap m_elementToAnimationsMap;
  • trunk/Source/WebCore/animation/CSSAnimation.cpp

    r251785 r252911  
    9898    animationEffect->setIterationDuration(Seconds(animation.duration()));
    9999    animationEffect->updateStaticTimingProperties();
     100    effectTimingDidChange();
    100101
    101102    // Synchronize the play state
  • trunk/Source/WebCore/animation/CSSTransition.cpp

    r251785 r252911  
    7575    animationEffect->setTimingFunction(backingAnimation().timingFunction());
    7676    animationEffect->updateStaticTimingProperties();
     77    effectTimingDidChange();
    7778
    7879    unsuspendEffectInvalidation();
  • trunk/Source/WebCore/animation/DeclarativeAnimation.cpp

    r251840 r252911  
    7070        m_eventQueue->close();
    7171    }
     72}
     73
     74bool DeclarativeAnimation::canHaveGlobalPosition()
     75{
     76    // https://drafts.csswg.org/css-animations-2/#animation-composite-order
     77    // https://drafts.csswg.org/css-transitions-2/#animation-composite-order
     78    // CSS Animations and CSS Transitions generated using the markup defined in this specification are not added
     79    // to the global animation list when they are created. Instead, these animations are appended to the global
     80    // animation list at the first moment when they transition out of the idle play state after being disassociated
     81    // from their owning element.
     82    return !m_owningElement && playState() != WebAnimation::PlayState::Idle;
    7283}
    7384
  • trunk/Source/WebCore/animation/DeclarativeAnimation.h

    r251742 r252911  
    6868    void tick() override;
    6969
     70    bool canHaveGlobalPosition() final;
     71
    7072protected:
    7173    DeclarativeAnimation(Element&, const Animation&);
  • trunk/Source/WebCore/animation/DocumentTimeline.cpp

    r252723 r252911  
    183183    });
    184184
     185    std::sort(webAnimations.begin(), webAnimations.end(), [](auto& lhs, auto& rhs) {
     186        return lhs->globalPosition() < rhs->globalPosition();
     187    });
     188
    185189    // Finally, we can concatenate the sorted CSS Transitions, CSS Animations and Web Animations in their relative composite order.
    186190    Vector<RefPtr<WebAnimation>> animations;
  • trunk/Source/WebCore/animation/KeyframeEffect.cpp

    r252724 r252911  
    997997
    998998    if (timeline)
    999         m_target->ensureKeyframeEffectStack().addEffect(*this);
    1000     else
     999        m_inTargetEffectStack = m_target->ensureKeyframeEffectStack().addEffect(*this);
     1000    else {
    10011001        m_target->ensureKeyframeEffectStack().removeEffect(*this);
     1002        m_inTargetEffectStack = false;
     1003    }
     1004}
     1005
     1006void KeyframeEffect::animationTimingDidChange()
     1007{
     1008    updateEffectStackMembership();
     1009}
     1010
     1011void KeyframeEffect::updateEffectStackMembership()
     1012{
     1013    if (!m_target)
     1014        return;
     1015
     1016    bool isRelevant = animation() && animation()->isRelevant();
     1017    if (isRelevant && !m_inTargetEffectStack)
     1018        m_inTargetEffectStack = m_target->ensureKeyframeEffectStack().addEffect(*this);
     1019    else if (!isRelevant && m_inTargetEffectStack) {
     1020        m_target->ensureKeyframeEffectStack().removeEffect(*this);
     1021        m_inTargetEffectStack = false;
     1022    }
    10021023}
    10031024
     
    10061027    bool animationChanged = animation != this->animation();
    10071028    AnimationEffect::setAnimation(animation);
    1008     if (m_target && animationChanged) {
    1009         if (animation)
    1010             m_target->ensureKeyframeEffectStack().addEffect(*this);
    1011         else
    1012             m_target->ensureKeyframeEffectStack().removeEffect(*this);
    1013     }
     1029
     1030    if (!animationChanged)
     1031        return;
     1032
     1033    if (animation)
     1034        animation->updateRelevance();
     1035    updateEffectStackMembership();
    10141036}
    10151037
     
    10341056    invalidateElement(previousTarget.get());
    10351057
    1036     if (previousTarget)
     1058    if (previousTarget) {
    10371059        previousTarget->ensureKeyframeEffectStack().removeEffect(*this);
     1060        m_inTargetEffectStack = false;
     1061    }
    10381062    if (m_target)
    1039         m_target->ensureKeyframeEffectStack().addEffect(*this);
     1063        m_inTargetEffectStack = m_target->ensureKeyframeEffectStack().addEffect(*this);
    10401064}
    10411065
  • trunk/Source/WebCore/animation/KeyframeEffect.h

    r252554 r252911  
    117117    void animationSuspensionStateDidChange(bool) final;
    118118    void animationTimelineDidChange(AnimationTimeline*) final;
     119    void animationTimingDidChange();
    119120    void applyPendingAcceleratedActions();
    120121    bool isRunningAccelerated() const { return m_lastRecordedAcceleratedAction != AcceleratedAction::Stop; }
     
    148149    enum class BlendingKeyframesSource : uint8_t { CSSAnimation, CSSTransition, WebAnimation };
    149150
     151    void updateEffectStackMembership();
    150152    void copyPropertiesFromSource(Ref<KeyframeEffect>&&);
    151153    ExceptionOr<void> processKeyframes(JSC::JSGlobalObject&, JSC::Strong<JSC::JSObject>&&);
     
    189191#endif
    190192    bool m_colorFilterFunctionListsMatch { false };
     193    bool m_inTargetEffectStack { false };
    191194};
    192195
  • trunk/Source/WebCore/animation/KeyframeEffectStack.cpp

    r252253 r252911  
    4343}
    4444
    45 void KeyframeEffectStack::addEffect(KeyframeEffect& effect)
     45bool KeyframeEffectStack::addEffect(KeyframeEffect& effect)
    4646{
    47     // To qualify for membership in an effect stack, an effect must have a target, an animation and a timeline.
     47    // To qualify for membership in an effect stack, an effect must have a target, an animation, a timeline and be relevant.
    4848    // This method will be called in WebAnimation and KeyframeEffect as those properties change.
    49     if (!effect.target() || !effect.animation() || !effect.animation()->timeline())
    50         return;
     49    if (!effect.target() || !effect.animation() || !effect.animation()->timeline() || !effect.animation()->isRelevant())
     50        return false;
    5151
    5252    m_effects.append(makeWeakPtr(&effect));
    5353    m_isSorted = false;
     54    return true;
    5455}
    5556
     
    7778        ASSERT(rhsAnimation);
    7879
     80        bool lhsHasOwningElement = is<DeclarativeAnimation>(lhsAnimation) && downcast<DeclarativeAnimation>(lhsAnimation)->owningElement();
     81        bool rhsHasOwningElement = is<DeclarativeAnimation>(rhsAnimation) && downcast<DeclarativeAnimation>(rhsAnimation)->owningElement();
     82
    7983        // CSS Transitions sort first.
    80         bool lhsIsCSSTransition = is<CSSTransition>(lhsAnimation);
    81         bool rhsIsCSSTransition = is<CSSTransition>(rhsAnimation);
     84        bool lhsIsCSSTransition = lhsHasOwningElement && is<CSSTransition>(lhsAnimation);
     85        bool rhsIsCSSTransition = rhsHasOwningElement && is<CSSTransition>(rhsAnimation);
    8286        if (lhsIsCSSTransition || rhsIsCSSTransition) {
    8387            if (lhsIsCSSTransition == rhsIsCSSTransition) {
     
    9498
    9599        // CSS Animations sort next.
    96         bool lhsIsCSSAnimation = is<CSSAnimation>(lhsAnimation);
    97         bool rhsIsCSSAnimation = is<CSSAnimation>(rhsAnimation);
     100        bool lhsIsCSSAnimation = lhsHasOwningElement && is<CSSAnimation>(lhsAnimation);
     101        bool rhsIsCSSAnimation = rhsHasOwningElement && is<CSSAnimation>(rhsAnimation);
    98102        if (lhsIsCSSAnimation || rhsIsCSSAnimation) {
    99103            if (lhsIsCSSAnimation == rhsIsCSSAnimation) {
  • trunk/Source/WebCore/animation/KeyframeEffectStack.h

    r252253 r252911  
    3939    ~KeyframeEffectStack();
    4040
    41     void addEffect(KeyframeEffect&);
     41    bool addEffect(KeyframeEffect&);
    4242    void removeEffect(KeyframeEffect&);
    4343    bool hasEffects() const { return !m_effects.isEmpty(); }
  • trunk/Source/WebCore/animation/WebAnimation.cpp

    r252723 r252911  
    722722    m_shouldSkipUpdatingFinishedStateWhenResolving = false;
    723723    updateFinishedState(didSeek, synchronouslyNotify);
     724
     725    if (is<KeyframeEffect>(m_effect)) {
     726        updateRelevance();
     727        downcast<KeyframeEffect>(*m_effect).animationTimingDidChange();
     728    }
     729
    724730    if (m_timeline)
    725731        m_timeline->animationTimingDidChange(*this);
  • trunk/Source/WebCore/animation/WebAnimation.h

    r252007 r252911  
    121121    bool isRunningAccelerated() const;
    122122    bool isRelevant() const { return m_isRelevant; }
     123    void updateRelevance();
    123124    void effectTimingDidChange();
    124125    void suspendEffectInvalidation();
     
    130131    void enqueueAnimationPlaybackEvent(const AtomString&, Optional<Seconds>, Optional<Seconds>);
    131132
    132     unsigned globalPosition() const { return m_globalPosition; }
    133     void setGlobalPosition(unsigned globalPosition) { m_globalPosition = globalPosition; }
     133    uint64_t globalPosition() const { return m_globalPosition; }
     134    void setGlobalPosition(uint64_t globalPosition) { m_globalPosition = globalPosition; }
    134135
    135136    bool hasPendingActivity() const final;
     137
     138    virtual bool canHaveGlobalPosition() { return true; }
    136139
    137140    // ContextDestructionObserver.
     
    170173    bool isEffectInvalidationSuspended() { return m_suspendCount; }
    171174    bool computeRelevance();
    172     void updateRelevance();
    173175    void invalidateEffect();
    174176    double effectivePlaybackRate() const;
     
    195197    TimeToRunPendingTask m_timeToRunPendingPauseTask { TimeToRunPendingTask::NotScheduled };
    196198    ReplaceState m_replaceState { ReplaceState::Active };
    197     unsigned m_globalPosition;
     199    uint64_t m_globalPosition { 0 };
    198200
    199201    // ActiveDOMObject.
Note: See TracChangeset for help on using the changeset viewer.