Title: [275346] trunk/Source/WebCore
Revision
275346
Author
grao...@webkit.org
Date
2021-03-31 23:33:21 -0700 (Wed, 31 Mar 2021)

Log Message

Move AnimationTimeline methods related to Styleable to Styleable
https://bugs.webkit.org/show_bug.cgi?id=224012

Reviewed by Dean Jackson.

A number of public methods on AnimationTimeline make no use of any AnimationTimeline instance
variables and instead call into Styleable:

    void elementWasRemoved(const Styleable&);
    void willChangeRendererForStyleable(const Styleable&);
    void cancelDeclarativeAnimationsForStyleable(const Styleable&);
    void animationWasAddedToStyleable(WebAnimation&, const Styleable&);
    void animationWasRemovedFromStyleable(WebAnimation&, const Styleable&);
    void removeDeclarativeAnimationFromListsForOwningElement(WebAnimation&, const Styleable&);
    void updateCSSAnimationsForStyleable(const Styleable&, const RenderStyle* currentStyle, const RenderStyle& afterChangeStyle, const RenderStyle* parentElementStyle);
    void updateCSSTransitionsForStyleable(const Styleable&, const RenderStyle& currentStyle, const RenderStyle& newStyle);

These really belong on Styleable so we move them all over to that class with a new .cpp class
for these non-trivial methods.

* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* animation/AnimationTimeline.cpp:
(WebCore::AnimationTimeline::removeAnimation):
(WebCore::AnimationTimeline::animationWasAddedToStyleable): Deleted.
(WebCore::removeCSSTransitionFromMap): Deleted.
(WebCore::AnimationTimeline::animationWasRemovedFromStyleable): Deleted.
(WebCore::AnimationTimeline::removeDeclarativeAnimationFromListsForOwningElement): Deleted.
(WebCore::AnimationTimeline::removeCSSAnimationCreatedByMarkup): Deleted.
(WebCore::AnimationTimeline::elementWasRemoved): Deleted.
(WebCore::AnimationTimeline::willChangeRendererForStyleable): Deleted.
(WebCore::AnimationTimeline::cancelDeclarativeAnimationsForStyleable): Deleted.
(WebCore::shouldConsiderAnimation): Deleted.
(WebCore::AnimationTimeline::updateCSSAnimationsForStyleable): Deleted.
(WebCore::keyframeEffectForElementAndProperty): Deleted.
(WebCore::propertyInStyleMatchesValueForTransitionInMap): Deleted.
(WebCore::transitionCombinedDuration): Deleted.
(WebCore::transitionMatchesProperty): Deleted.
(WebCore::compileTransitionPropertiesInStyle): Deleted.
(WebCore::AnimationTimeline::updateCSSTransitionsForStyleableAndProperty): Deleted.
(WebCore::AnimationTimeline::updateCSSTransitionsForStyleable): Deleted.
* animation/AnimationTimeline.h:
* animation/DeclarativeAnimation.cpp:
(WebCore::DeclarativeAnimation::disassociateFromOwningElement):
* animation/WebAnimation.cpp:
(WebCore::WebAnimation::setEffectInternal):
(WebCore::WebAnimation::setTimeline):
(WebCore::WebAnimation::effectTargetDidChange):
(WebCore::WebAnimation::persist):
* dom/Element.cpp:
(WebCore::Element::removedFromAncestor):
* dom/PseudoElement.cpp:
(WebCore::PseudoElement::clearHostElement):
* rendering/updating/RenderTreeUpdater.cpp:
(WebCore::RenderTreeUpdater::tearDownRenderers):
* style/StyleTreeResolver.cpp:
(WebCore::Style::TreeResolver::createAnimatedElementUpdate):
* style/Styleable.cpp: Copied from Source/WebCore/animation/AnimationTimeline.cpp.
(WebCore::Styleable::animationWasAdded const):
(WebCore::removeCSSTransitionFromMap):
(WebCore::Styleable::removeDeclarativeAnimationFromListsForOwningElement const):
(WebCore::Styleable::animationWasRemoved const):
(WebCore::removeCSSAnimationCreatedByMarkup):
(WebCore::Styleable::elementWasRemoved const):
(WebCore::Styleable::willChangeRenderer const):
(WebCore::Styleable::cancelDeclarativeAnimations const):
(WebCore::shouldConsiderAnimation):
(WebCore::Styleable::updateCSSAnimations const):
(WebCore::keyframeEffectForElementAndProperty):
(WebCore::propertyInStyleMatchesValueForTransitionInMap):
(WebCore::transitionCombinedDuration):
(WebCore::transitionMatchesProperty):
(WebCore::compileTransitionPropertiesInStyle):
(WebCore::updateCSSTransitionsForStyleableAndProperty):
(WebCore::Styleable::updateCSSTransitions const):
* style/Styleable.h:

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (275345 => 275346)


--- trunk/Source/WebCore/ChangeLog	2021-04-01 04:03:47 UTC (rev 275345)
+++ trunk/Source/WebCore/ChangeLog	2021-04-01 06:33:21 UTC (rev 275346)
@@ -1,3 +1,82 @@
+2021-03-31  Antoine Quint  <grao...@webkit.org>
+
+        Move AnimationTimeline methods related to Styleable to Styleable
+        https://bugs.webkit.org/show_bug.cgi?id=224012
+
+        Reviewed by Dean Jackson.
+
+        A number of public methods on AnimationTimeline make no use of any AnimationTimeline instance
+        variables and instead call into Styleable:
+
+            void elementWasRemoved(const Styleable&);
+            void willChangeRendererForStyleable(const Styleable&);
+            void cancelDeclarativeAnimationsForStyleable(const Styleable&);
+            void animationWasAddedToStyleable(WebAnimation&, const Styleable&);
+            void animationWasRemovedFromStyleable(WebAnimation&, const Styleable&);
+            void removeDeclarativeAnimationFromListsForOwningElement(WebAnimation&, const Styleable&);
+            void updateCSSAnimationsForStyleable(const Styleable&, const RenderStyle* currentStyle, const RenderStyle& afterChangeStyle, const RenderStyle* parentElementStyle);
+            void updateCSSTransitionsForStyleable(const Styleable&, const RenderStyle& currentStyle, const RenderStyle& newStyle);
+
+        These really belong on Styleable so we move them all over to that class with a new .cpp class
+        for these non-trivial methods.
+
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * animation/AnimationTimeline.cpp:
+        (WebCore::AnimationTimeline::removeAnimation):
+        (WebCore::AnimationTimeline::animationWasAddedToStyleable): Deleted.
+        (WebCore::removeCSSTransitionFromMap): Deleted.
+        (WebCore::AnimationTimeline::animationWasRemovedFromStyleable): Deleted.
+        (WebCore::AnimationTimeline::removeDeclarativeAnimationFromListsForOwningElement): Deleted.
+        (WebCore::AnimationTimeline::removeCSSAnimationCreatedByMarkup): Deleted.
+        (WebCore::AnimationTimeline::elementWasRemoved): Deleted.
+        (WebCore::AnimationTimeline::willChangeRendererForStyleable): Deleted.
+        (WebCore::AnimationTimeline::cancelDeclarativeAnimationsForStyleable): Deleted.
+        (WebCore::shouldConsiderAnimation): Deleted.
+        (WebCore::AnimationTimeline::updateCSSAnimationsForStyleable): Deleted.
+        (WebCore::keyframeEffectForElementAndProperty): Deleted.
+        (WebCore::propertyInStyleMatchesValueForTransitionInMap): Deleted.
+        (WebCore::transitionCombinedDuration): Deleted.
+        (WebCore::transitionMatchesProperty): Deleted.
+        (WebCore::compileTransitionPropertiesInStyle): Deleted.
+        (WebCore::AnimationTimeline::updateCSSTransitionsForStyleableAndProperty): Deleted.
+        (WebCore::AnimationTimeline::updateCSSTransitionsForStyleable): Deleted.
+        * animation/AnimationTimeline.h:
+        * animation/DeclarativeAnimation.cpp:
+        (WebCore::DeclarativeAnimation::disassociateFromOwningElement):
+        * animation/WebAnimation.cpp:
+        (WebCore::WebAnimation::setEffectInternal):
+        (WebCore::WebAnimation::setTimeline):
+        (WebCore::WebAnimation::effectTargetDidChange):
+        (WebCore::WebAnimation::persist):
+        * dom/Element.cpp:
+        (WebCore::Element::removedFromAncestor):
+        * dom/PseudoElement.cpp:
+        (WebCore::PseudoElement::clearHostElement):
+        * rendering/updating/RenderTreeUpdater.cpp:
+        (WebCore::RenderTreeUpdater::tearDownRenderers):
+        * style/StyleTreeResolver.cpp:
+        (WebCore::Style::TreeResolver::createAnimatedElementUpdate):
+        * style/Styleable.cpp: Copied from Source/WebCore/animation/AnimationTimeline.cpp.
+        (WebCore::Styleable::animationWasAdded const):
+        (WebCore::removeCSSTransitionFromMap):
+        (WebCore::Styleable::removeDeclarativeAnimationFromListsForOwningElement const):
+        (WebCore::Styleable::animationWasRemoved const):
+        (WebCore::removeCSSAnimationCreatedByMarkup):
+        (WebCore::Styleable::elementWasRemoved const):
+        (WebCore::Styleable::willChangeRenderer const):
+        (WebCore::Styleable::cancelDeclarativeAnimations const):
+        (WebCore::shouldConsiderAnimation):
+        (WebCore::Styleable::updateCSSAnimations const):
+        (WebCore::keyframeEffectForElementAndProperty):
+        (WebCore::propertyInStyleMatchesValueForTransitionInMap):
+        (WebCore::transitionCombinedDuration):
+        (WebCore::transitionMatchesProperty):
+        (WebCore::compileTransitionPropertiesInStyle):
+        (WebCore::updateCSSTransitionsForStyleableAndProperty):
+        (WebCore::Styleable::updateCSSTransitions const):
+        * style/Styleable.h:
+
 2021-03-31  Simon Fraser  <simon.fra...@apple.com>
 
         Feed preferred frames per second back to the UI process for each DisplayRefreshMonitor

Modified: trunk/Source/WebCore/Sources.txt (275345 => 275346)


--- trunk/Source/WebCore/Sources.txt	2021-04-01 04:03:47 UTC (rev 275345)
+++ trunk/Source/WebCore/Sources.txt	2021-04-01 06:33:21 UTC (rev 275346)
@@ -2496,6 +2496,7 @@
 style/StyleSharingResolver.cpp
 style/StyleTreeResolver.cpp
 style/StyleUpdate.cpp
+style/Styleable.cpp
 style/UserAgentStyle.cpp
 svg/DocumentSVG.cpp
 svg/SVGAElement.cpp

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (275345 => 275346)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-04-01 04:03:47 UTC (rev 275345)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-04-01 06:33:21 UTC (rev 275346)
@@ -10151,6 +10151,7 @@
 		71729F7A20F3BA3A00801CE6 /* DocumentTimelineOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocumentTimelineOptions.h; sourceTree = "<group>"; };
 		71729F7C20F3BAB900801CE6 /* JSDocumentTimelineOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDocumentTimelineOptions.h; sourceTree = "<group>"; };
 		71729F7D20F3BABA00801CE6 /* JSDocumentTimelineOptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDocumentTimelineOptions.cpp; sourceTree = "<group>"; };
+		7173DEBD2614DF040097DF32 /* Styleable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Styleable.cpp; sourceTree = "<group>"; };
 		7177E2461DB80D2F00919A0B /* media-controller-support.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; path = "media-controller-support.js"; sourceTree = "<group>"; };
 		7177E2471DB80D2F00919A0B /* mute-support.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; path = "mute-support.js"; sourceTree = "<group>"; };
 		7177E2481DB80D2F00919A0B /* start-support.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; path = "start-support.js"; sourceTree = "<group>"; };
@@ -29317,6 +29318,7 @@
 				A79BAD9E161E7F3F00C2E652 /* RuleFeature.h */,
 				A79BAD9F161E7F3F00C2E652 /* RuleSet.cpp */,
 				A79BADA0161E7F3F00C2E652 /* RuleSet.h */,
+				7173DEBD2614DF040097DF32 /* Styleable.cpp */,
 				713922BC2518AB70005DB3C2 /* Styleable.h */,
 				E45BA6B22376227E004DFC07 /* StyleAdjuster.cpp */,
 				E45BA6B52376229F004DFC07 /* StyleAdjuster.h */,

Modified: trunk/Source/WebCore/animation/AnimationTimeline.cpp (275345 => 275346)


--- trunk/Source/WebCore/animation/AnimationTimeline.cpp	2021-04-01 04:03:47 UTC (rev 275345)
+++ trunk/Source/WebCore/animation/AnimationTimeline.cpp	2021-04-01 06:33:21 UTC (rev 275346)
@@ -27,25 +27,11 @@
 #include "config.h"
 #include "AnimationTimeline.h"
 
-#include "Animation.h"
-#include "AnimationEffect.h"
-#include "AnimationList.h"
-#include "CSSAnimation.h"
-#include "CSSPropertyAnimation.h"
-#include "CSSTransition.h"
-#include "DocumentTimeline.h"
-#include "Element.h"
 #include "KeyframeEffect.h"
 #include "KeyframeEffectStack.h"
-#include "PseudoElement.h"
-#include "RenderStyle.h"
-#include "RenderView.h"
-#include "StylePropertyShorthand.h"
 #include "StyleResolver.h"
 #include "Styleable.h"
 #include "WebAnimationUtilities.h"
-#include <wtf/text/TextStream.h>
-#include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
@@ -82,7 +68,7 @@
     m_animations.remove(&animation);
     if (is<KeyframeEffect>(animation.effect())) {
         if (auto styleable = downcast<KeyframeEffect>(animation.effect())->targetStyleable()) {
-            animationWasRemovedFromStyleable(animation, *styleable);
+            styleable->animationWasRemoved(animation);
             styleable->ensureKeyframeEffectStack().removeEffect(*downcast<KeyframeEffect>(animation.effect()));
         }
     }
@@ -96,454 +82,4 @@
     return secondsToWebAnimationsAPITime(*time);
 }
 
-void AnimationTimeline::animationWasAddedToStyleable(WebAnimation& animation, const Styleable& styleable)
-{
-    styleable.ensureAnimations().add(&animation);
-}
-
-static inline bool removeCSSTransitionFromMap(CSSTransition& transition, PropertyToTransitionMap& cssTransitionsByProperty)
-{
-    auto transitionIterator = cssTransitionsByProperty.find(transition.property());
-    if (transitionIterator == cssTransitionsByProperty.end() || transitionIterator->value != &transition)
-        return false;
-
-    cssTransitionsByProperty.remove(transitionIterator);
-    return true;
-}
-
-void AnimationTimeline::animationWasRemovedFromStyleable(WebAnimation& animation, const Styleable& styleable)
-{
-    styleable.ensureAnimations().remove(&animation);
-
-    // Now, if we're dealing with a CSS Transition, we remove it from the m_elementToRunningCSSTransitionByCSSPropertyID map.
-    // We don't need to do this for CSS Animations because their timing can be set via CSS to end, which would cause this
-    // function to be called, but they should remain associated with their owning element until this is changed via a call
-    // to the JS API or changing the target element's animation-name property.
-    if (is<CSSTransition>(animation))
-        removeDeclarativeAnimationFromListsForOwningElement(animation, styleable);
-}
-
-void AnimationTimeline::removeDeclarativeAnimationFromListsForOwningElement(WebAnimation& animation, const Styleable& styleable)
-{
-    ASSERT(is<DeclarativeAnimation>(animation));
-
-    if (is<CSSTransition>(animation)) {
-        auto& transition = downcast<CSSTransition>(animation);
-        if (!removeCSSTransitionFromMap(transition, styleable.ensureRunningTransitionsByProperty()))
-            removeCSSTransitionFromMap(transition, styleable.ensureCompletedTransitionsByProperty());
-    }
-}
-
-void AnimationTimeline::removeCSSAnimationCreatedByMarkup(const Styleable& styleable, CSSAnimation& cssAnimation)
-{
-    styleable.animationsCreatedByMarkup().remove(&cssAnimation);
-
-    if (!styleable.hasKeyframeEffects())
-        return;
-
-    auto& keyframeEffectStack = styleable.ensureKeyframeEffectStack();
-    auto* cssAnimationList = keyframeEffectStack.cssAnimationList();
-    if (!cssAnimationList || cssAnimationList->isEmpty())
-        return;
-
-    auto& backingAnimation = cssAnimation.backingAnimation();
-    for (size_t i = 0; i < cssAnimationList->size(); ++i) {
-        if (cssAnimationList->animation(i) == backingAnimation) {
-            auto newAnimationList = cssAnimationList->copy();
-            newAnimationList->remove(i);
-            keyframeEffectStack.setCSSAnimationList(WTFMove(newAnimationList));
-            return;
-        }
-    }
-}
-
-void AnimationTimeline::elementWasRemoved(const Styleable& styleable)
-{
-    cancelDeclarativeAnimationsForStyleable(styleable);
-}
-
-void AnimationTimeline::willChangeRendererForStyleable(const Styleable& styleable)
-{
-    if (auto* animations = styleable.animations()) {
-        for (const auto& animation : *animations)
-            animation->willChangeRenderer();
-    }
-}
-
-void AnimationTimeline::cancelDeclarativeAnimationsForStyleable(const Styleable& styleable)
-{
-    if (auto* animations = styleable.animations()) {
-        for (auto& animation : *animations) {
-            if (is<DeclarativeAnimation>(animation)) {
-                if (is<CSSAnimation>(animation))
-                    removeCSSAnimationCreatedByMarkup(styleable, downcast<CSSAnimation>(*animation));
-                downcast<DeclarativeAnimation>(*animation).cancelFromStyle();
-            }
-        }
-    }
-}
-
-static bool shouldConsiderAnimation(Element& element, const Animation& animation)
-{
-    if (!animation.isValidAnimation())
-        return false;
-
-    static NeverDestroyed<const String> animationNameNone(MAKE_STATIC_STRING_IMPL("none"));
-
-    auto& name = animation.name();
-    if (name == animationNameNone || name.isEmpty())
-        return false;
-
-    if (auto* styleScope = Style::Scope::forOrdinal(element, animation.nameStyleScopeOrdinal()))
-        return styleScope->resolver().isAnimationNameValid(name);
-
-    return false;
-}
-
-void AnimationTimeline::updateCSSAnimationsForStyleable(const Styleable& styleable, const RenderStyle* currentStyle, const RenderStyle& newStyle, const RenderStyle* parentElementStyle)
-{
-    auto& keyframeEffectStack = styleable.ensureKeyframeEffectStack();
-
-    // In case this element is newly getting a "display: none" we need to cancel all of its animations and disregard new ones.
-    if (currentStyle && currentStyle->display() != DisplayType::None && newStyle.display() == DisplayType::None) {
-        for (auto& cssAnimation : styleable.animationsCreatedByMarkup())
-            cssAnimation->cancelFromStyle();
-        keyframeEffectStack.setCSSAnimationList(nullptr);
-        return;
-    }
-
-    auto* currentAnimationList = newStyle.animations();
-    auto* previousAnimationList = keyframeEffectStack.cssAnimationList();
-    if (previousAnimationList && !previousAnimationList->isEmpty() && newStyle.hasAnimations() && *(previousAnimationList) == *(newStyle.animations()))
-        return;
-
-    CSSAnimationCollection newAnimations;
-    auto& previousAnimations = styleable.animationsCreatedByMarkup();
-
-    // https://www.w3.org/TR/css-animations-1/#animations
-    // The same @keyframes rule name may be repeated within an animation-name. Changes to the animation-name update existing
-    // animations by iterating over the new list of animations from last to first, and, for each animation, finding the last
-    // matching animation in the list of existing animations. If a match is found, the existing animation is updated using the
-    // animation properties corresponding to its position in the new list of animations, whilst maintaining its current playback
-    // time as described above. The matching animation is removed from the existing list of animations such that it will not match
-    // twice. If a match is not found, a new animation is created. As a result, updating animation-name from ‘a’ to ‘a, a’ will
-    // cause the existing animation for ‘a’ to become the second animation in the list and a new animation will be created for the
-    // first item in the list.
-    if (currentAnimationList) {
-        for (size_t i = currentAnimationList->size(); i > 0; --i) {
-            auto& currentAnimation = currentAnimationList->animation(i - 1);
-            if (!shouldConsiderAnimation(styleable.element, currentAnimation))
-                continue;
-
-            bool foundMatchingAnimation = false;
-            for (auto& previousAnimation : previousAnimations) {
-                if (previousAnimation->animationName() == currentAnimation.name()) {
-                    // Timing properties or play state may have changed so we need to update the backing animation with
-                    // the Animation found in the current style.
-                    previousAnimation->setBackingAnimation(currentAnimation);
-                    newAnimations.add(previousAnimation);
-                    // Remove the matched animation from the list of previous animations so we may not match it again.
-                    previousAnimations.remove(previousAnimation);
-                    foundMatchingAnimation = true;
-                    break;
-                }
-            }
-
-            if (!foundMatchingAnimation)
-                newAnimations.add(CSSAnimation::create(styleable, currentAnimation, currentStyle, newStyle, parentElementStyle));
-        }
-    }
-
-    // Any animation found in previousAnimations but not found in newAnimations is not longer current and should be canceled.
-    for (auto& previousAnimation : previousAnimations) {
-        if (!newAnimations.contains(previousAnimation)) {
-            if (previousAnimation->owningElement())
-                previousAnimation->cancelFromStyle();
-        }
-    }
-
-    styleable.setAnimationsCreatedByMarkup(WTFMove(newAnimations));
-
-    keyframeEffectStack.setCSSAnimationList(currentAnimationList);
-}
-
-static KeyframeEffect* keyframeEffectForElementAndProperty(const Styleable& styleable, CSSPropertyID property)
-{
-    if (auto* keyframeEffectStack = styleable.keyframeEffectStack()) {
-        auto effects = keyframeEffectStack->sortedEffects();
-        for (const auto& effect : makeReversedRange(effects)) {
-            if (effect->animatesProperty(property))
-                return effect.get();
-        }
-    }
-
-    return nullptr;
-}
-
-static bool propertyInStyleMatchesValueForTransitionInMap(CSSPropertyID property, const RenderStyle& style, PropertyToTransitionMap& transitions)
-{
-    if (auto* transition = transitions.get(property)) {
-        if (CSSPropertyAnimation::propertiesEqual(property, &style, &transition->targetStyle()))
-            return true;
-    }
-    return false;
-}
-
-static double transitionCombinedDuration(const Animation* transition)
-{
-    return std::max(0.0, transition->duration()) + transition->delay();
-}
-
-static bool transitionMatchesProperty(const Animation& transition, CSSPropertyID property)
-{
-    auto mode = transition.property().mode;
-    if (mode == Animation::TransitionMode::None || mode == Animation::TransitionMode::UnknownProperty)
-        return false;
-    if (mode == Animation::TransitionMode::SingleProperty) {
-        auto transitionProperty = transition.property().id;
-        if (transitionProperty != property) {
-            for (auto longhand : shorthandForProperty(transitionProperty)) {
-                if (longhand == property)
-                    return true;
-            }
-            return false;
-        }
-    }
-    return true;
-}
-
-static void compileTransitionPropertiesInStyle(const RenderStyle& style, HashSet<CSSPropertyID>& transitionProperties, bool& transitionPropertiesContainAll)
-{
-    if (transitionPropertiesContainAll)
-        return;
-
-    auto* transitions = style.transitions();
-    if (!transitions)
-        return;
-
-    for (size_t i = 0; i < transitions->size(); ++i) {
-        const auto& animation = transitions->animation(i);
-        auto mode = animation.property().mode;
-        if (mode == Animation::TransitionMode::SingleProperty) {
-            auto property = animation.property().id;
-            if (isShorthandCSSProperty(property)) {
-                for (auto longhand : shorthandForProperty(property))
-                    transitionProperties.add(longhand);
-            } else if (property != CSSPropertyInvalid)
-                transitionProperties.add(property);
-        } else if (mode == Animation::TransitionMode::All) {
-            transitionPropertiesContainAll = true;
-            return;
-        }
-    }
-}
-
-void AnimationTimeline::updateCSSTransitionsForStyleableAndProperty(const Styleable& styleable, CSSPropertyID property, const RenderStyle& currentStyle, const RenderStyle& newStyle, const MonotonicTime generationTime)
-{
-    auto* keyframeEffect = keyframeEffectForElementAndProperty(styleable, property);
-    auto* animation = keyframeEffect ? keyframeEffect->animation() : nullptr;
-
-    bool isDeclarative = false;
-    if (is<DeclarativeAnimation>(animation)) {
-        if (auto owningElement = downcast<DeclarativeAnimation>(*animation).owningElement())
-            isDeclarative = *owningElement == styleable;
-    }
-
-    if (animation && !isDeclarative)
-        return;
-
-    const Animation* matchingBackingAnimation = nullptr;
-    if (auto* transitions = newStyle.transitions()) {
-        for (size_t i = 0; i < transitions->size(); ++i) {
-            auto& backingAnimation = transitions->animation(i);
-            if (transitionMatchesProperty(backingAnimation, property))
-                matchingBackingAnimation = &backingAnimation;
-        }
-    }
-
-    // A CSS Transition might have completed since the last time animations were updated so we must
-    // update the running and completed transitions membership in that case.
-    if (is<CSSTransition>(animation) && matchingBackingAnimation && styleable.hasRunningTransitionForProperty(property) && animation->playState() == WebAnimation::PlayState::Finished) {
-        styleable.ensureCompletedTransitionsByProperty().set(property, styleable.ensureRunningTransitionsByProperty().take(property));
-        animation = nullptr;
-    }
-
-    // https://drafts.csswg.org/css-transitions-1/#before-change-style
-    // Define the before-change style as the computed values of all properties on the element as of the previous style change event, except with
-    // any styles derived from declarative animations such as CSS Transitions, CSS Animations, and SMIL Animations updated to the current time.
-    auto beforeChangeStyle = [&]() -> const RenderStyle {
-        if (animation && animation->isRelevant()) {
-            auto animatedStyle = RenderStyle::clone(currentStyle);
-            // If a transition has not yet started or started when animations were last updated, use the timeline time at its creation
-            // as its start time to ensure that it will produce a style with progress > 0.
-            bool shouldUseTimelineTimeAtCreation = is<CSSTransition>(animation) && (!animation->startTime() || *animation->startTime() == currentTime());
-            animation->resolve(animatedStyle, nullptr, shouldUseTimelineTimeAtCreation ? downcast<CSSTransition>(*animation).timelineTimeAtCreation() : WTF::nullopt);
-            return animatedStyle;
-        }
-
-        // If it exists, use the recorded RenderStyle for this element during a previous call to Style::TreeResolver::createAnimatedElementUpdate().
-        if (auto* lastStyleChangeEventStyle = styleable.lastStyleChangeEventStyle())
-            return RenderStyle::clone(*lastStyleChangeEventStyle);
-
-        // If we haven't computed styles from animations for this element, the before-change style is the previously resolved style for this element.
-        return RenderStyle::clone(currentStyle);
-    }();
-
-    // https://drafts.csswg.org/css-transitions-1/#after-change-style
-    // Likewise, define the after-change style as the computed values of all properties on the element based on the information known at the start
-    // of that style change event, but using the computed values of the animation-* properties from the before-change style, excluding any styles
-    // from CSS Transitions in the computation, and inheriting from the after-change style of the parent. Note that this means the after-change
-    // style does not differ from the before-change style due to newly created or canceled CSS Animations.
-    auto afterChangeStyle = [&]() -> const RenderStyle {
-        if (is<CSSAnimation>(animation) && animation->isRelevant()) {
-            auto animatedStyle = RenderStyle::clone(newStyle);
-            animation->resolve(animatedStyle, nullptr);
-            return animatedStyle;
-        }
-
-        return RenderStyle::clone(newStyle);
-    }();
-
-    if (!styleable.hasRunningTransitionForProperty(property)
-        && !CSSPropertyAnimation::propertiesEqual(property, &beforeChangeStyle, &afterChangeStyle)
-        && CSSPropertyAnimation::canPropertyBeInterpolated(property, &beforeChangeStyle, &afterChangeStyle)
-        && !propertyInStyleMatchesValueForTransitionInMap(property, afterChangeStyle, styleable.ensureCompletedTransitionsByProperty())
-        && matchingBackingAnimation && transitionCombinedDuration(matchingBackingAnimation) > 0) {
-        // 1. If all of the following are true:
-        //   - the element does not have a running transition for the property,
-        //   - the before-change style is different from and can be interpolated with the after-change style for that property,
-        //   - the element does not have a completed transition for the property or the end value of the completed transition is different from the after-change style for the property,
-        //   - there is a matching transition-property value, and
-        //   - the combined duration is greater than 0s,
-
-        // then implementations must remove the completed transition (if present) from the set of completed transitions
-        styleable.ensureCompletedTransitionsByProperty().remove(property);
-
-        // and start a transition whose:
-        //   - start time is the time of the style change event plus the matching transition delay,
-        //   - end time is the start time plus the matching transition duration,
-        //   - start value is the value of the transitioning property in the before-change style,
-        //   - end value is the value of the transitioning property in the after-change style,
-        //   - reversing-adjusted start value is the same as the start value, and
-        //   - reversing shortening factor is 1.
-        auto delay = Seconds(matchingBackingAnimation->delay());
-        auto duration = Seconds(matchingBackingAnimation->duration());
-        auto& reversingAdjustedStartStyle = beforeChangeStyle;
-        auto reversingShorteningFactor = 1;
-        styleable.ensureRunningTransitionsByProperty().set(property, CSSTransition::create(styleable, property, generationTime, *matchingBackingAnimation, &beforeChangeStyle, afterChangeStyle, delay, duration, reversingAdjustedStartStyle, reversingShorteningFactor));
-    } else if (styleable.hasCompletedTransitionForProperty(property) && !propertyInStyleMatchesValueForTransitionInMap(property, afterChangeStyle, styleable.ensureCompletedTransitionsByProperty())) {
-        // 2. Otherwise, if the element has a completed transition for the property and the end value of the completed transition is different from
-        //    the after-change style for the property, then implementations must remove the completed transition from the set of completed transitions.
-        styleable.ensureCompletedTransitionsByProperty().remove(property);
-    }
-
-    bool hasRunningTransition = styleable.hasRunningTransitionForProperty(property);
-    if ((hasRunningTransition || styleable.hasCompletedTransitionForProperty(property)) && !matchingBackingAnimation) {
-        // 3. If the element has a running transition or completed transition for the property, and there is not a matching transition-property
-        //    value, then implementations must cancel the running transition or remove the completed transition from the set of completed transitions.
-        if (hasRunningTransition)
-            styleable.ensureRunningTransitionsByProperty().take(property)->cancel();
-        else
-            styleable.ensureCompletedTransitionsByProperty().remove(property);
-    }
-
-    if (matchingBackingAnimation && styleable.hasRunningTransitionForProperty(property) && !propertyInStyleMatchesValueForTransitionInMap(property, afterChangeStyle, styleable.ensureRunningTransitionsByProperty())) {
-        auto previouslyRunningTransition = styleable.ensureRunningTransitionsByProperty().take(property);
-        auto& previouslyRunningTransitionCurrentStyle = previouslyRunningTransition->currentStyle();
-        // 4. If the element has a running transition for the property, there is a matching transition-property value, and the end value of the running
-        //    transition is not equal to the value of the property in the after-change style, then:
-        if (CSSPropertyAnimation::propertiesEqual(property, &previouslyRunningTransitionCurrentStyle, &afterChangeStyle) || !CSSPropertyAnimation::canPropertyBeInterpolated(property, &currentStyle, &afterChangeStyle)) {
-            // 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,
-            //    or if these two values cannot be interpolated, then implementations must cancel the running transition.
-            previouslyRunningTransition->cancelFromStyle();
-        } else if (transitionCombinedDuration(matchingBackingAnimation) <= 0.0 || !CSSPropertyAnimation::canPropertyBeInterpolated(property, &previouslyRunningTransitionCurrentStyle, &afterChangeStyle)) {
-            // 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
-            //    cannot be interpolated with the value of the property in the after-change style, then implementations must cancel the running transition.
-            previouslyRunningTransition->cancelFromStyle();
-        } else if (CSSPropertyAnimation::propertiesEqual(property, &previouslyRunningTransition->reversingAdjustedStartStyle(), &afterChangeStyle)) {
-            // 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
-            //    style (see the section on reversing of transitions for why these case exists), implementations must cancel the running transition
-            previouslyRunningTransition->cancelFromStyle();
-
-            // and start a new transition whose:
-            //   - reversing-adjusted start value is the end value of the running transition,
-            //   - reversing shortening factor is the absolute value, clamped to the range [0, 1], of the sum of:
-            //       1. the output of the timing function of the old transition at the time of the style change event, times the reversing shortening factor of the old transition
-            //       2. 1 minus the reversing shortening factor of the old transition.
-            //   - start time is the time of the style change event plus:
-            //       1. if the matching transition delay is nonnegative, the matching transition delay, or
-            //       2. if the matching transition delay is negative, the product of the new transition’s reversing shortening factor and the matching transition delay,
-            //   - end time is the start time plus the product of the matching transition duration and the new transition’s reversing shortening factor,
-            //   - start value is the current value of the property in the running transition,
-            //   - end value is the value of the property in the after-change style
-            auto& reversingAdjustedStartStyle = previouslyRunningTransition->targetStyle();
-            double transformedProgress = 1;
-            if (auto* effect = previouslyRunningTransition->effect()) {
-                if (auto computedTimingProgress = effect->getComputedTiming().progress)
-                    transformedProgress = *computedTimingProgress;
-            }
-            auto reversingShorteningFactor = std::max(std::min(((transformedProgress * previouslyRunningTransition->reversingShorteningFactor()) + (1 - previouslyRunningTransition->reversingShorteningFactor())), 1.0), 0.0);
-            auto delay = matchingBackingAnimation->delay() < 0 ? Seconds(matchingBackingAnimation->delay()) * reversingShorteningFactor : Seconds(matchingBackingAnimation->delay());
-            auto duration = Seconds(matchingBackingAnimation->duration()) * reversingShorteningFactor;
-
-            styleable.ensureRunningTransitionsByProperty().set(property, CSSTransition::create(styleable, property, generationTime, *matchingBackingAnimation, &previouslyRunningTransitionCurrentStyle, afterChangeStyle, delay, duration, reversingAdjustedStartStyle, reversingShorteningFactor));
-        } else {
-            // 4. Otherwise, implementations must cancel the running transition
-            previouslyRunningTransition->cancelFromStyle();
-
-            // and start a new transition whose:
-            //   - start time is the time of the style change event plus the matching transition delay,
-            //   - end time is the start time plus the matching transition duration,
-            //   - start value is the current value of the property in the running transition,
-            //   - end value is the value of the property in the after-change style,
-            //   - reversing-adjusted start value is the same as the start value, and
-            //   - reversing shortening factor is 1.
-            auto delay = Seconds(matchingBackingAnimation->delay());
-            auto duration = Seconds(matchingBackingAnimation->duration());
-            auto& reversingAdjustedStartStyle = currentStyle;
-            auto reversingShorteningFactor = 1;
-            styleable.ensureRunningTransitionsByProperty().set(property, CSSTransition::create(styleable, property, generationTime, *matchingBackingAnimation, &previouslyRunningTransitionCurrentStyle, afterChangeStyle, delay, duration, reversingAdjustedStartStyle, reversingShorteningFactor));
-        }
-    }
-}
-
-void AnimationTimeline::updateCSSTransitionsForStyleable(const Styleable& styleable, const RenderStyle& currentStyle, const RenderStyle& newStyle)
-{
-    // In case this element is newly getting a "display: none" we need to cancel all of its transitions and disregard new ones.
-    if (currentStyle.hasTransitions() && currentStyle.display() != DisplayType::None && newStyle.display() == DisplayType::None) {
-        if (styleable.hasRunningTransitions()) {
-            auto runningTransitions = styleable.ensureRunningTransitionsByProperty();
-            for (const auto& cssTransitionsByCSSPropertyIDMapItem : runningTransitions)
-                cssTransitionsByCSSPropertyIDMapItem.value->cancelFromStyle();
-        }
-        return;
-    }
-
-    // Section 3 "Starting of transitions" from the CSS Transitions Level 1 specification.
-    // https://drafts.csswg.org/css-transitions-1/#starting
-
-    auto generationTime = MonotonicTime::now();
-
-    // First, let's compile the list of all CSS properties found in the current style and the after-change style.
-    bool transitionPropertiesContainAll = false;
-    HashSet<CSSPropertyID> transitionProperties;
-    compileTransitionPropertiesInStyle(currentStyle, transitionProperties, transitionPropertiesContainAll);
-    compileTransitionPropertiesInStyle(newStyle, transitionProperties, transitionPropertiesContainAll);
-
-    if (transitionPropertiesContainAll) {
-        auto numberOfProperties = CSSPropertyAnimation::getNumProperties();
-        for (int propertyIndex = 0; propertyIndex < numberOfProperties; ++propertyIndex) {
-            Optional<bool> isShorthand;
-            auto property = CSSPropertyAnimation::getPropertyAtIndex(propertyIndex, isShorthand);
-            if (isShorthand && *isShorthand)
-                continue;
-            updateCSSTransitionsForStyleableAndProperty(styleable, property, currentStyle, newStyle, generationTime);
-        }
-        return;
-    }
-
-    for (auto property : transitionProperties)
-        updateCSSTransitionsForStyleableAndProperty(styleable, property, currentStyle, newStyle, generationTime);
-}
-
 } // namespace WebCore

Modified: trunk/Source/WebCore/animation/AnimationTimeline.h (275345 => 275346)


--- trunk/Source/WebCore/animation/AnimationTimeline.h	2021-04-01 04:03:47 UTC (rev 275345)
+++ trunk/Source/WebCore/animation/AnimationTimeline.h	2021-04-01 06:33:21 UTC (rev 275346)
@@ -26,14 +26,9 @@
 
 #pragma once
 
-#include "CSSValue.h"
-#include "ComputedEffectTiming.h"
 #include "RenderStyle.h"
-#include "Styleable.h"
 #include "WebAnimation.h"
 #include <wtf/Forward.h>
-#include <wtf/HashMap.h>
-#include <wtf/ListHashSet.h>
 #include <wtf/Markable.h>
 #include <wtf/Optional.h>
 #include <wtf/Ref.h>
@@ -42,10 +37,6 @@
 
 namespace WebCore {
 
-class CSSAnimation;
-class CSSTransition;
-class DeclarativeAnimation;
-
 class AnimationTimeline : public RefCounted<AnimationTimeline>, public CanMakeWeakPtr<AnimationTimeline> {
 public:
     virtual ~AnimationTimeline();
@@ -61,19 +52,6 @@
     Optional<double> bindingsCurrentTime();
     virtual Optional<Seconds> currentTime() { return m_currentTime; }
 
-    void elementWasRemoved(const Styleable&);
-
-    void willChangeRendererForStyleable(const Styleable&);
-    void cancelDeclarativeAnimationsForStyleable(const Styleable&);
-
-    void animationWasAddedToStyleable(WebAnimation&, const Styleable&);
-    void animationWasRemovedFromStyleable(WebAnimation&, const Styleable&);
-
-    void removeDeclarativeAnimationFromListsForOwningElement(WebAnimation&, const Styleable&);
-
-    void updateCSSAnimationsForStyleable(const Styleable&, const RenderStyle* currentStyle, const RenderStyle& afterChangeStyle, const RenderStyle* parentElementStyle);
-    void updateCSSTransitionsForStyleable(const Styleable&, const RenderStyle& currentStyle, const RenderStyle& newStyle);
-
 protected:
     explicit AnimationTimeline();
 
@@ -82,8 +60,6 @@
 
 private:
     void updateGlobalPosition(WebAnimation&);
-    void updateCSSTransitionsForStyleableAndProperty(const Styleable&, CSSPropertyID, const RenderStyle& currentStyle, const RenderStyle& afterChangeStyle, const MonotonicTime);
-    void removeCSSAnimationCreatedByMarkup(const Styleable&, CSSAnimation&);
 
     Markable<Seconds, Seconds::MarkableTraits> m_currentTime;
 };

Modified: trunk/Source/WebCore/animation/DeclarativeAnimation.cpp (275345 => 275346)


--- trunk/Source/WebCore/animation/DeclarativeAnimation.cpp	2021-04-01 04:03:47 UTC (rev 275345)
+++ trunk/Source/WebCore/animation/DeclarativeAnimation.cpp	2021-04-01 06:33:21 UTC (rev 275346)
@@ -95,8 +95,7 @@
     if (!m_owningElement)
         return;
 
-    if (auto* animationTimeline = timeline())
-        animationTimeline->removeDeclarativeAnimationFromListsForOwningElement(*this, *owningElement());
+    owningElement()->removeDeclarativeAnimationFromListsForOwningElement(*this);
     m_owningElement = nullptr;
 }
 

Modified: trunk/Source/WebCore/animation/WebAnimation.cpp (275345 => 275346)


--- trunk/Source/WebCore/animation/WebAnimation.cpp	2021-04-01 04:03:47 UTC (rev 275345)
+++ trunk/Source/WebCore/animation/WebAnimation.cpp	2021-04-01 06:33:21 UTC (rev 275346)
@@ -212,15 +212,15 @@
     // Update the effect-to-animation relationships and the timeline's animation map.
     if (oldEffect) {
         oldEffect->setAnimation(nullptr);
-        if (!doNotRemoveFromTimeline && m_timeline && previousTarget && previousTarget != newTarget)
-            m_timeline->animationWasRemovedFromStyleable(*this, *previousTarget);
+        if (!doNotRemoveFromTimeline && previousTarget && previousTarget != newTarget)
+            previousTarget->animationWasRemoved(*this);
         updateRelevance();
     }
 
     if (m_effect) {
         m_effect->setAnimation(this);
-        if (m_timeline && newTarget && previousTarget != newTarget)
-            m_timeline->animationWasAddedToStyleable(*this, *newTarget);
+        if (newTarget && previousTarget != newTarget)
+            newTarget->animationWasAdded(*this);
     }
 
     InspectorInstrumentation::didSetWebAnimationEffect(*this);
@@ -244,10 +244,9 @@
             // In the case of a declarative animation, we don't want to remove the animation from the relevant maps because
             // while the timeline was set via the API, the element still has a transition or animation set up and we must
             // not break the relationship.
-            if (m_timeline && !isDeclarativeAnimation())
-                m_timeline->animationWasRemovedFromStyleable(*this, *target);
-            if (timeline)
-                timeline->animationWasAddedToStyleable(*this, *target);
+            if (!isDeclarativeAnimation())
+                target->animationWasRemoved(*this);
+            target->animationWasAdded(*this);
         }
     }
 
@@ -282,10 +281,10 @@
 {
     if (m_timeline) {
         if (previousTarget)
-            m_timeline->animationWasRemovedFromStyleable(*this, *previousTarget);
+            previousTarget->animationWasRemoved(*this);
 
         if (newTarget)
-            m_timeline->animationWasAddedToStyleable(*this, *newTarget);
+            newTarget->animationWasAdded(*this);
 
         // This could have changed whether we have replaced animations, so we may need to schedule an update.
         m_timeline->animationTimingDidChange(*this);
@@ -1368,7 +1367,7 @@
         if (is<KeyframeEffect>(m_effect)) {
             auto& keyframeEffect = downcast<KeyframeEffect>(*m_effect);
             auto styleable = keyframeEffect.targetStyleable();
-            m_timeline->animationWasAddedToStyleable(*this, *styleable);
+            styleable->animationWasAdded(*this);
             styleable->ensureKeyframeEffectStack().addEffect(keyframeEffect);
         }
     }

Modified: trunk/Source/WebCore/dom/Element.cpp (275345 => 275346)


--- trunk/Source/WebCore/dom/Element.cpp	2021-04-01 04:03:47 UTC (rev 275345)
+++ trunk/Source/WebCore/dom/Element.cpp	2021-04-01 06:33:21 UTC (rev 275346)
@@ -2317,8 +2317,7 @@
         document().accessSVGExtensions().removeElementFromPendingResources(*this);
 
     RefPtr<Frame> frame = document().frame();
-    if (auto* timeline = document().existingTimeline())
-        timeline->elementWasRemoved({ *this, pseudoId() });
+    Styleable::fromElement(*this).elementWasRemoved();
 
 #if ENABLE(WHEEL_EVENT_LATCHING)
     if (frame && frame->page()) {

Modified: trunk/Source/WebCore/dom/PseudoElement.cpp (275345 => 275346)


--- trunk/Source/WebCore/dom/PseudoElement.cpp	2021-04-01 04:03:47 UTC (rev 275345)
+++ trunk/Source/WebCore/dom/PseudoElement.cpp	2021-04-01 06:33:21 UTC (rev 275346)
@@ -75,8 +75,7 @@
 {
     InspectorInstrumentation::pseudoElementDestroyed(document().page(), *this);
 
-    if (auto* timeline = document().existingTimeline())
-        timeline->elementWasRemoved(Styleable::fromElement(*this));
+    Styleable::fromElement(*this).elementWasRemoved();
     
     m_hostElement = nullptr;
 }

Modified: trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.cpp (275345 => 275346)


--- trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.cpp	2021-04-01 04:03:47 UTC (rev 275345)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.cpp	2021-04-01 06:33:21 UTC (rev 275346)
@@ -556,7 +556,6 @@
     };
 
     auto& document = root.document();
-    auto* timeline = document.existingTimeline();
 
     auto pop = [&] (unsigned depth) {
         while (teardownStack.size() > depth) {
@@ -569,16 +568,11 @@
             switch (teardownType) {
             case TeardownType::Full:
             case TeardownType::RendererUpdateCancelingAnimations:
-                if (timeline) {
-                    if (document.renderTreeBeingDestroyed())
-                        timeline->cancelDeclarativeAnimationsForStyleable(Styleable::fromElement(element));
-                    else if (teardownType == TeardownType::RendererUpdateCancelingAnimations)
-                        timeline->cancelDeclarativeAnimationsForStyleable(Styleable::fromElement(element));
-                }
+                if (document.renderTreeBeingDestroyed() || teardownType == TeardownType::RendererUpdateCancelingAnimations)
+                    Styleable::fromElement(element).cancelDeclarativeAnimations();
                 break;
             case TeardownType::RendererUpdate:
-                if (timeline)
-                    timeline->willChangeRendererForStyleable(Styleable::fromElement(element));
+                Styleable::fromElement(element).willChangeRenderer();
                 break;
             }
 

Modified: trunk/Source/WebCore/style/StyleTreeResolver.cpp (275345 => 275346)


--- trunk/Source/WebCore/style/StyleTreeResolver.cpp	2021-04-01 04:03:47 UTC (rev 275345)
+++ trunk/Source/WebCore/style/StyleTreeResolver.cpp	2021-04-01 06:33:21 UTC (rev 275346)
@@ -332,13 +332,13 @@
     // in case no Web Animations have been created through the JS API.
     if (document.backForwardCacheState() == Document::NotInBackForwardCache && !document.renderView()->printing()) {
         if (oldStyle && (oldStyle->hasTransitions() || newStyle->hasTransitions()))
-            document.timeline().updateCSSTransitionsForStyleable(styleable, *oldStyle, *newStyle);
+            styleable.updateCSSTransitions(*oldStyle, *newStyle);
 
         // The order in which CSS Transitions and CSS Animations are updated matters since CSS Transitions define the after-change style
         // to use CSS Animations as defined in the previous style change event. As such, we update CSS Animations after CSS Transitions
         // such that when CSS Transitions are updated the CSS Animations data is the same as during the previous style change event.
         if ((oldStyle && oldStyle->hasAnimations()) || newStyle->hasAnimations())
-            document.timeline().updateCSSAnimationsForStyleable(styleable, oldStyle, *newStyle, &parentStyle);
+            styleable.updateCSSAnimations(oldStyle, *newStyle, &parentStyle);
     }
 
     // Now we can update all Web animations, which will include CSS Animations as well

Copied: trunk/Source/WebCore/style/Styleable.cpp (from rev 275345, trunk/Source/WebCore/animation/AnimationTimeline.cpp) (0 => 275346)


--- trunk/Source/WebCore/style/Styleable.cpp	                        (rev 0)
+++ trunk/Source/WebCore/style/Styleable.cpp	2021-04-01 06:33:21 UTC (rev 275346)
@@ -0,0 +1,498 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Styleable.h"
+
+#include "Animation.h"
+#include "AnimationEffect.h"
+#include "AnimationList.h"
+#include "AnimationTimeline.h"
+#include "CSSAnimation.h"
+#include "CSSPropertyAnimation.h"
+#include "CSSTransition.h"
+#include "DeclarativeAnimation.h"
+#include "Document.h"
+#include "Element.h"
+#include "KeyframeEffect.h"
+#include "KeyframeEffectStack.h"
+#include "RenderStyle.h"
+#include "StylePropertyShorthand.h"
+#include "WebAnimation.h"
+#include "WebAnimationUtilities.h"
+
+namespace WebCore {
+
+void Styleable::animationWasAdded(WebAnimation& animation) const
+{
+    ensureAnimations().add(&animation);
+}
+
+static inline bool removeCSSTransitionFromMap(CSSTransition& transition, PropertyToTransitionMap& cssTransitionsByProperty)
+{
+    auto transitionIterator = cssTransitionsByProperty.find(transition.property());
+    if (transitionIterator == cssTransitionsByProperty.end() || transitionIterator->value != &transition)
+        return false;
+
+    cssTransitionsByProperty.remove(transitionIterator);
+    return true;
+}
+
+void Styleable::removeDeclarativeAnimationFromListsForOwningElement(WebAnimation& animation) const
+{
+    ASSERT(is<DeclarativeAnimation>(animation));
+
+    if (is<CSSTransition>(animation)) {
+        auto& transition = downcast<CSSTransition>(animation);
+        if (!removeCSSTransitionFromMap(transition, ensureRunningTransitionsByProperty()))
+            removeCSSTransitionFromMap(transition, ensureCompletedTransitionsByProperty());
+    }
+}
+
+void Styleable::animationWasRemoved(WebAnimation& animation) const
+{
+    ensureAnimations().remove(&animation);
+
+    // Now, if we're dealing with a CSS Transition, we remove it from the m_elementToRunningCSSTransitionByCSSPropertyID map.
+    // We don't need to do this for CSS Animations because their timing can be set via CSS to end, which would cause this
+    // function to be called, but they should remain associated with their owning element until this is changed via a call
+    // to the JS API or changing the target element's animation-name property.
+    if (is<CSSTransition>(animation))
+        removeDeclarativeAnimationFromListsForOwningElement(animation);
+}
+
+static void removeCSSAnimationCreatedByMarkup(const Styleable& styleable, CSSAnimation& cssAnimation)
+{
+    styleable.animationsCreatedByMarkup().remove(&cssAnimation);
+
+    if (!styleable.hasKeyframeEffects())
+        return;
+
+    auto& keyframeEffectStack = styleable.ensureKeyframeEffectStack();
+    auto* cssAnimationList = keyframeEffectStack.cssAnimationList();
+    if (!cssAnimationList || cssAnimationList->isEmpty())
+        return;
+
+    auto& backingAnimation = cssAnimation.backingAnimation();
+    for (size_t i = 0; i < cssAnimationList->size(); ++i) {
+        if (cssAnimationList->animation(i) == backingAnimation) {
+            auto newAnimationList = cssAnimationList->copy();
+            newAnimationList->remove(i);
+            keyframeEffectStack.setCSSAnimationList(WTFMove(newAnimationList));
+            return;
+        }
+    }
+}
+
+void Styleable::elementWasRemoved() const
+{
+    cancelDeclarativeAnimations();
+}
+
+void Styleable::willChangeRenderer() const
+{
+    if (auto* animations = this->animations()) {
+        for (const auto& animation : *animations)
+            animation->willChangeRenderer();
+    }
+}
+
+void Styleable::cancelDeclarativeAnimations() const
+{
+    if (auto* animations = this->animations()) {
+        for (auto& animation : *animations) {
+            if (is<DeclarativeAnimation>(animation)) {
+                if (is<CSSAnimation>(animation))
+                    removeCSSAnimationCreatedByMarkup(*this, downcast<CSSAnimation>(*animation));
+                downcast<DeclarativeAnimation>(*animation).cancelFromStyle();
+            }
+        }
+    }
+}
+
+static bool shouldConsiderAnimation(Element& element, const Animation& animation)
+{
+    if (!animation.isValidAnimation())
+        return false;
+
+    static NeverDestroyed<const String> animationNameNone(MAKE_STATIC_STRING_IMPL("none"));
+
+    auto& name = animation.name();
+    if (name == animationNameNone || name.isEmpty())
+        return false;
+
+    if (auto* styleScope = Style::Scope::forOrdinal(element, animation.nameStyleScopeOrdinal()))
+        return styleScope->resolver().isAnimationNameValid(name);
+
+    return false;
+}
+
+void Styleable::updateCSSAnimations(const RenderStyle* currentStyle, const RenderStyle& newStyle, const RenderStyle* parentElementStyle) const
+{
+    auto& keyframeEffectStack = ensureKeyframeEffectStack();
+
+    // In case this element is newly getting a "display: none" we need to cancel all of its animations and disregard new ones.
+    if (currentStyle && currentStyle->display() != DisplayType::None && newStyle.display() == DisplayType::None) {
+        for (auto& cssAnimation : animationsCreatedByMarkup())
+            cssAnimation->cancelFromStyle();
+        keyframeEffectStack.setCSSAnimationList(nullptr);
+        return;
+    }
+
+    auto* currentAnimationList = newStyle.animations();
+    auto* previousAnimationList = keyframeEffectStack.cssAnimationList();
+    if (previousAnimationList && !previousAnimationList->isEmpty() && newStyle.hasAnimations() && *(previousAnimationList) == *(newStyle.animations()))
+        return;
+
+    CSSAnimationCollection newAnimations;
+    auto& previousAnimations = animationsCreatedByMarkup();
+
+    // https://www.w3.org/TR/css-animations-1/#animations
+    // The same @keyframes rule name may be repeated within an animation-name. Changes to the animation-name update existing
+    // animations by iterating over the new list of animations from last to first, and, for each animation, finding the last
+    // matching animation in the list of existing animations. If a match is found, the existing animation is updated using the
+    // animation properties corresponding to its position in the new list of animations, whilst maintaining its current playback
+    // time as described above. The matching animation is removed from the existing list of animations such that it will not match
+    // twice. If a match is not found, a new animation is created. As a result, updating animation-name from ‘a’ to ‘a, a’ will
+    // cause the existing animation for ‘a’ to become the second animation in the list and a new animation will be created for the
+    // first item in the list.
+    if (currentAnimationList) {
+        for (size_t i = currentAnimationList->size(); i > 0; --i) {
+            auto& currentAnimation = currentAnimationList->animation(i - 1);
+            if (!shouldConsiderAnimation(this->element, currentAnimation))
+                continue;
+
+            bool foundMatchingAnimation = false;
+            for (auto& previousAnimation : previousAnimations) {
+                if (previousAnimation->animationName() == currentAnimation.name()) {
+                    // Timing properties or play state may have changed so we need to update the backing animation with
+                    // the Animation found in the current style.
+                    previousAnimation->setBackingAnimation(currentAnimation);
+                    newAnimations.add(previousAnimation);
+                    // Remove the matched animation from the list of previous animations so we may not match it again.
+                    previousAnimations.remove(previousAnimation);
+                    foundMatchingAnimation = true;
+                    break;
+                }
+            }
+
+            if (!foundMatchingAnimation)
+                newAnimations.add(CSSAnimation::create(*this, currentAnimation, currentStyle, newStyle, parentElementStyle));
+        }
+    }
+
+    // Any animation found in previousAnimations but not found in newAnimations is not longer current and should be canceled.
+    for (auto& previousAnimation : previousAnimations) {
+        if (!newAnimations.contains(previousAnimation)) {
+            if (previousAnimation->owningElement())
+                previousAnimation->cancelFromStyle();
+        }
+    }
+
+    setAnimationsCreatedByMarkup(WTFMove(newAnimations));
+
+    keyframeEffectStack.setCSSAnimationList(currentAnimationList);
+}
+
+static KeyframeEffect* keyframeEffectForElementAndProperty(const Styleable& styleable, CSSPropertyID property)
+{
+    if (auto* keyframeEffectStack = styleable.keyframeEffectStack()) {
+        auto effects = keyframeEffectStack->sortedEffects();
+        for (const auto& effect : makeReversedRange(effects)) {
+            if (effect->animatesProperty(property))
+                return effect.get();
+        }
+    }
+
+    return nullptr;
+}
+
+static bool propertyInStyleMatchesValueForTransitionInMap(CSSPropertyID property, const RenderStyle& style, PropertyToTransitionMap& transitions)
+{
+    if (auto* transition = transitions.get(property)) {
+        if (CSSPropertyAnimation::propertiesEqual(property, &style, &transition->targetStyle()))
+            return true;
+    }
+    return false;
+}
+
+static double transitionCombinedDuration(const Animation* transition)
+{
+    return std::max(0.0, transition->duration()) + transition->delay();
+}
+
+static bool transitionMatchesProperty(const Animation& transition, CSSPropertyID property)
+{
+    auto mode = transition.property().mode;
+    if (mode == Animation::TransitionMode::None || mode == Animation::TransitionMode::UnknownProperty)
+        return false;
+    if (mode == Animation::TransitionMode::SingleProperty) {
+        auto transitionProperty = transition.property().id;
+        if (transitionProperty != property) {
+            for (auto longhand : shorthandForProperty(transitionProperty)) {
+                if (longhand == property)
+                    return true;
+            }
+            return false;
+        }
+    }
+    return true;
+}
+
+static void compileTransitionPropertiesInStyle(const RenderStyle& style, HashSet<CSSPropertyID>& transitionProperties, bool& transitionPropertiesContainAll)
+{
+    if (transitionPropertiesContainAll)
+        return;
+
+    auto* transitions = style.transitions();
+    if (!transitions)
+        return;
+
+    for (size_t i = 0; i < transitions->size(); ++i) {
+        const auto& animation = transitions->animation(i);
+        auto mode = animation.property().mode;
+        if (mode == Animation::TransitionMode::SingleProperty) {
+            auto property = animation.property().id;
+            if (isShorthandCSSProperty(property)) {
+                for (auto longhand : shorthandForProperty(property))
+                    transitionProperties.add(longhand);
+            } else if (property != CSSPropertyInvalid)
+                transitionProperties.add(property);
+        } else if (mode == Animation::TransitionMode::All) {
+            transitionPropertiesContainAll = true;
+            return;
+        }
+    }
+}
+
+static void updateCSSTransitionsForStyleableAndProperty(const Styleable& styleable, CSSPropertyID property, const RenderStyle& currentStyle, const RenderStyle& newStyle, const MonotonicTime generationTime)
+{
+    auto* keyframeEffect = keyframeEffectForElementAndProperty(styleable, property);
+    auto* animation = keyframeEffect ? keyframeEffect->animation() : nullptr;
+
+    bool isDeclarative = false;
+    if (is<DeclarativeAnimation>(animation)) {
+        if (auto owningElement = downcast<DeclarativeAnimation>(*animation).owningElement())
+            isDeclarative = *owningElement == styleable;
+    }
+
+    if (animation && !isDeclarative)
+        return;
+
+    const Animation* matchingBackingAnimation = nullptr;
+    if (auto* transitions = newStyle.transitions()) {
+        for (size_t i = 0; i < transitions->size(); ++i) {
+            auto& backingAnimation = transitions->animation(i);
+            if (transitionMatchesProperty(backingAnimation, property))
+                matchingBackingAnimation = &backingAnimation;
+        }
+    }
+
+    // A CSS Transition might have completed since the last time animations were updated so we must
+    // update the running and completed transitions membership in that case.
+    if (is<CSSTransition>(animation) && matchingBackingAnimation && styleable.hasRunningTransitionForProperty(property) && animation->playState() == WebAnimation::PlayState::Finished) {
+        styleable.ensureCompletedTransitionsByProperty().set(property, styleable.ensureRunningTransitionsByProperty().take(property));
+        animation = nullptr;
+    }
+
+    // https://drafts.csswg.org/css-transitions-1/#before-change-style
+    // Define the before-change style as the computed values of all properties on the element as of the previous style change event, except with
+    // any styles derived from declarative animations such as CSS Transitions, CSS Animations, and SMIL Animations updated to the current time.
+    auto beforeChangeStyle = [&]() -> const RenderStyle {
+        if (animation && animation->isRelevant()) {
+            auto animatedStyle = RenderStyle::clone(currentStyle);
+            // If a transition has not yet started or started when animations were last updated, use the timeline time at its creation
+            // as its start time to ensure that it will produce a style with progress > 0.
+            bool shouldUseTimelineTimeAtCreation = is<CSSTransition>(animation) && (!animation->startTime() || *animation->startTime() == styleable.element.document().timeline().currentTime());
+            animation->resolve(animatedStyle, nullptr, shouldUseTimelineTimeAtCreation ? downcast<CSSTransition>(*animation).timelineTimeAtCreation() : WTF::nullopt);
+            return animatedStyle;
+        }
+
+        // If it exists, use the recorded RenderStyle for this element during a previous call to Style::TreeResolver::createAnimatedElementUpdate().
+        if (auto* lastStyleChangeEventStyle = styleable.lastStyleChangeEventStyle())
+            return RenderStyle::clone(*lastStyleChangeEventStyle);
+
+        // If we haven't computed styles from animations for this element, the before-change style is the previously resolved style for this element.
+        return RenderStyle::clone(currentStyle);
+    }();
+
+    // https://drafts.csswg.org/css-transitions-1/#after-change-style
+    // Likewise, define the after-change style as the computed values of all properties on the element based on the information known at the start
+    // of that style change event, but using the computed values of the animation-* properties from the before-change style, excluding any styles
+    // from CSS Transitions in the computation, and inheriting from the after-change style of the parent. Note that this means the after-change
+    // style does not differ from the before-change style due to newly created or canceled CSS Animations.
+    auto afterChangeStyle = [&]() -> const RenderStyle {
+        if (is<CSSAnimation>(animation) && animation->isRelevant()) {
+            auto animatedStyle = RenderStyle::clone(newStyle);
+            animation->resolve(animatedStyle, nullptr);
+            return animatedStyle;
+        }
+
+        return RenderStyle::clone(newStyle);
+    }();
+
+    if (!styleable.hasRunningTransitionForProperty(property)
+        && !CSSPropertyAnimation::propertiesEqual(property, &beforeChangeStyle, &afterChangeStyle)
+        && CSSPropertyAnimation::canPropertyBeInterpolated(property, &beforeChangeStyle, &afterChangeStyle)
+        && !propertyInStyleMatchesValueForTransitionInMap(property, afterChangeStyle, styleable.ensureCompletedTransitionsByProperty())
+        && matchingBackingAnimation && transitionCombinedDuration(matchingBackingAnimation) > 0) {
+        // 1. If all of the following are true:
+        //   - the element does not have a running transition for the property,
+        //   - the before-change style is different from and can be interpolated with the after-change style for that property,
+        //   - the element does not have a completed transition for the property or the end value of the completed transition is different from the after-change style for the property,
+        //   - there is a matching transition-property value, and
+        //   - the combined duration is greater than 0s,
+
+        // then implementations must remove the completed transition (if present) from the set of completed transitions
+        styleable.ensureCompletedTransitionsByProperty().remove(property);
+
+        // and start a transition whose:
+        //   - start time is the time of the style change event plus the matching transition delay,
+        //   - end time is the start time plus the matching transition duration,
+        //   - start value is the value of the transitioning property in the before-change style,
+        //   - end value is the value of the transitioning property in the after-change style,
+        //   - reversing-adjusted start value is the same as the start value, and
+        //   - reversing shortening factor is 1.
+        auto delay = Seconds(matchingBackingAnimation->delay());
+        auto duration = Seconds(matchingBackingAnimation->duration());
+        auto& reversingAdjustedStartStyle = beforeChangeStyle;
+        auto reversingShorteningFactor = 1;
+        styleable.ensureRunningTransitionsByProperty().set(property, CSSTransition::create(styleable, property, generationTime, *matchingBackingAnimation, &beforeChangeStyle, afterChangeStyle, delay, duration, reversingAdjustedStartStyle, reversingShorteningFactor));
+    } else if (styleable.hasCompletedTransitionForProperty(property) && !propertyInStyleMatchesValueForTransitionInMap(property, afterChangeStyle, styleable.ensureCompletedTransitionsByProperty())) {
+        // 2. Otherwise, if the element has a completed transition for the property and the end value of the completed transition is different from
+        //    the after-change style for the property, then implementations must remove the completed transition from the set of completed transitions.
+        styleable.ensureCompletedTransitionsByProperty().remove(property);
+    }
+
+    bool hasRunningTransition = styleable.hasRunningTransitionForProperty(property);
+    if ((hasRunningTransition || styleable.hasCompletedTransitionForProperty(property)) && !matchingBackingAnimation) {
+        // 3. If the element has a running transition or completed transition for the property, and there is not a matching transition-property
+        //    value, then implementations must cancel the running transition or remove the completed transition from the set of completed transitions.
+        if (hasRunningTransition)
+            styleable.ensureRunningTransitionsByProperty().take(property)->cancel();
+        else
+            styleable.ensureCompletedTransitionsByProperty().remove(property);
+    }
+
+    if (matchingBackingAnimation && styleable.hasRunningTransitionForProperty(property) && !propertyInStyleMatchesValueForTransitionInMap(property, afterChangeStyle, styleable.ensureRunningTransitionsByProperty())) {
+        auto previouslyRunningTransition = styleable.ensureRunningTransitionsByProperty().take(property);
+        auto& previouslyRunningTransitionCurrentStyle = previouslyRunningTransition->currentStyle();
+        // 4. If the element has a running transition for the property, there is a matching transition-property value, and the end value of the running
+        //    transition is not equal to the value of the property in the after-change style, then:
+        if (CSSPropertyAnimation::propertiesEqual(property, &previouslyRunningTransitionCurrentStyle, &afterChangeStyle) || !CSSPropertyAnimation::canPropertyBeInterpolated(property, &currentStyle, &afterChangeStyle)) {
+            // 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,
+            //    or if these two values cannot be interpolated, then implementations must cancel the running transition.
+            previouslyRunningTransition->cancelFromStyle();
+        } else if (transitionCombinedDuration(matchingBackingAnimation) <= 0.0 || !CSSPropertyAnimation::canPropertyBeInterpolated(property, &previouslyRunningTransitionCurrentStyle, &afterChangeStyle)) {
+            // 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
+            //    cannot be interpolated with the value of the property in the after-change style, then implementations must cancel the running transition.
+            previouslyRunningTransition->cancelFromStyle();
+        } else if (CSSPropertyAnimation::propertiesEqual(property, &previouslyRunningTransition->reversingAdjustedStartStyle(), &afterChangeStyle)) {
+            // 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
+            //    style (see the section on reversing of transitions for why these case exists), implementations must cancel the running transition
+            previouslyRunningTransition->cancelFromStyle();
+
+            // and start a new transition whose:
+            //   - reversing-adjusted start value is the end value of the running transition,
+            //   - reversing shortening factor is the absolute value, clamped to the range [0, 1], of the sum of:
+            //       1. the output of the timing function of the old transition at the time of the style change event, times the reversing shortening factor of the old transition
+            //       2. 1 minus the reversing shortening factor of the old transition.
+            //   - start time is the time of the style change event plus:
+            //       1. if the matching transition delay is nonnegative, the matching transition delay, or
+            //       2. if the matching transition delay is negative, the product of the new transition’s reversing shortening factor and the matching transition delay,
+            //   - end time is the start time plus the product of the matching transition duration and the new transition’s reversing shortening factor,
+            //   - start value is the current value of the property in the running transition,
+            //   - end value is the value of the property in the after-change style
+            auto& reversingAdjustedStartStyle = previouslyRunningTransition->targetStyle();
+            double transformedProgress = 1;
+            if (auto* effect = previouslyRunningTransition->effect()) {
+                if (auto computedTimingProgress = effect->getComputedTiming().progress)
+                    transformedProgress = *computedTimingProgress;
+            }
+            auto reversingShorteningFactor = std::max(std::min(((transformedProgress * previouslyRunningTransition->reversingShorteningFactor()) + (1 - previouslyRunningTransition->reversingShorteningFactor())), 1.0), 0.0);
+            auto delay = matchingBackingAnimation->delay() < 0 ? Seconds(matchingBackingAnimation->delay()) * reversingShorteningFactor : Seconds(matchingBackingAnimation->delay());
+            auto duration = Seconds(matchingBackingAnimation->duration()) * reversingShorteningFactor;
+
+            styleable.ensureRunningTransitionsByProperty().set(property, CSSTransition::create(styleable, property, generationTime, *matchingBackingAnimation, &previouslyRunningTransitionCurrentStyle, afterChangeStyle, delay, duration, reversingAdjustedStartStyle, reversingShorteningFactor));
+        } else {
+            // 4. Otherwise, implementations must cancel the running transition
+            previouslyRunningTransition->cancelFromStyle();
+
+            // and start a new transition whose:
+            //   - start time is the time of the style change event plus the matching transition delay,
+            //   - end time is the start time plus the matching transition duration,
+            //   - start value is the current value of the property in the running transition,
+            //   - end value is the value of the property in the after-change style,
+            //   - reversing-adjusted start value is the same as the start value, and
+            //   - reversing shortening factor is 1.
+            auto delay = Seconds(matchingBackingAnimation->delay());
+            auto duration = Seconds(matchingBackingAnimation->duration());
+            auto& reversingAdjustedStartStyle = currentStyle;
+            auto reversingShorteningFactor = 1;
+            styleable.ensureRunningTransitionsByProperty().set(property, CSSTransition::create(styleable, property, generationTime, *matchingBackingAnimation, &previouslyRunningTransitionCurrentStyle, afterChangeStyle, delay, duration, reversingAdjustedStartStyle, reversingShorteningFactor));
+        }
+    }
+}
+
+void Styleable::updateCSSTransitions(const RenderStyle& currentStyle, const RenderStyle& newStyle) const
+{
+    // In case this element is newly getting a "display: none" we need to cancel all of its transitions and disregard new ones.
+    if (currentStyle.hasTransitions() && currentStyle.display() != DisplayType::None && newStyle.display() == DisplayType::None) {
+        if (hasRunningTransitions()) {
+            auto runningTransitions = ensureRunningTransitionsByProperty();
+            for (const auto& cssTransitionsByCSSPropertyIDMapItem : runningTransitions)
+                cssTransitionsByCSSPropertyIDMapItem.value->cancelFromStyle();
+        }
+        return;
+    }
+
+    // Section 3 "Starting of transitions" from the CSS Transitions Level 1 specification.
+    // https://drafts.csswg.org/css-transitions-1/#starting
+
+    auto generationTime = MonotonicTime::now();
+
+    // First, let's compile the list of all CSS properties found in the current style and the after-change style.
+    bool transitionPropertiesContainAll = false;
+    HashSet<CSSPropertyID> transitionProperties;
+    compileTransitionPropertiesInStyle(currentStyle, transitionProperties, transitionPropertiesContainAll);
+    compileTransitionPropertiesInStyle(newStyle, transitionProperties, transitionPropertiesContainAll);
+
+    if (transitionPropertiesContainAll) {
+        auto numberOfProperties = CSSPropertyAnimation::getNumProperties();
+        for (int propertyIndex = 0; propertyIndex < numberOfProperties; ++propertyIndex) {
+            Optional<bool> isShorthand;
+            auto property = CSSPropertyAnimation::getPropertyAtIndex(propertyIndex, isShorthand);
+            if (isShorthand && *isShorthand)
+                continue;
+            updateCSSTransitionsForStyleableAndProperty(*this, property, currentStyle, newStyle, generationTime);
+        }
+        return;
+    }
+
+    for (auto property : transitionProperties)
+        updateCSSTransitionsForStyleableAndProperty(*this, property, currentStyle, newStyle, generationTime);
+}
+
+} // namespace WebCore

Modified: trunk/Source/WebCore/style/Styleable.h (275345 => 275346)


--- trunk/Source/WebCore/style/Styleable.h	2021-04-01 04:03:47 UTC (rev 275345)
+++ trunk/Source/WebCore/style/Styleable.h	2021-04-01 06:33:21 UTC (rev 275346)
@@ -31,11 +31,13 @@
 #include "RenderElement.h"
 #include "RenderStyleConstants.h"
 #include "WebAnimationTypes.h"
+#include <wtf/Optional.h>
 
 namespace WebCore {
 
 class KeyframeEffectStack;
 class RenderStyle;
+class WebAnimation;
 
 struct Styleable {
     Element& element;
@@ -147,6 +149,18 @@
         element.setLastStyleChangeEventStyle(pseudoId, WTFMove(style));
     }
 
+    void elementWasRemoved() const;
+
+    void willChangeRenderer() const;
+    void cancelDeclarativeAnimations() const;
+
+    void animationWasAdded(WebAnimation&) const;
+    void animationWasRemoved(WebAnimation&) const;
+
+    void removeDeclarativeAnimationFromListsForOwningElement(WebAnimation&) const;
+
+    void updateCSSAnimations(const RenderStyle* currentStyle, const RenderStyle& afterChangeStyle, const RenderStyle* parentElementStyle) const;
+    void updateCSSTransitions(const RenderStyle& currentStyle, const RenderStyle& newStyle) const;
 };
 
 } // namespace WebCore
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to