WebKit Bugzilla
Attachment 342939 Details for
Bug 186517
: [Web Animations] Implement "Starting of transitions" section from CSS Transitions
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-186517-20180618175019.patch (text/plain), 82.95 KB, created by
Antoine Quint
on 2018-06-18 08:50:21 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Antoine Quint
Created:
2018-06-18 08:50:21 PDT
Size:
82.95 KB
patch
obsolete
>Subversion Revision: 232930 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index b6f561ae62f46d5f200b4fabd3fd15184df6b5d5..a9cf1db4d82867cade8f18f540877baa2700bf80 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,65 @@ >+2018-06-18 Antoine Quint <graouts@apple.com> >+ >+ [Web Animations] Implement "Starting of transitions" section from CSS Transitions >+ https://bugs.webkit.org/show_bug.cgi?id=186517 >+ <rdar://problem/41000798> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ We implement the whole section at https://drafts.csswg.org/css-transitions-1/#starting so that we have spec-compliant starting of CSS Transitions. >+ To correctly implement this we now maintain two maps of transitions for a given property, a set of running transitions (m_elementToRunningCSSTransitionByCSSPropertyID) >+ and a set of completed transition (m_elementToCompletedCSSTransitionByCSSPropertyID). >+ >+ * animation/AnimationTimeline.cpp: >+ (WebCore::removeCSSTransitionFromMap): Add a utility to remove a CSSTransition from one of the two HashMap<Element*, HashMap<CSSPropertyID, RefPtr<CSSTransition>>> >+ managed by AnimationTimeline (m_elementToRunningCSSTransitionByCSSPropertyID and m_elementToCompletedCSSTransitionByCSSPropertyID). >+ (WebCore::AnimationTimeline::animationWasRemovedFromElement): Use the new removeCSSTransitionFromMap() utility. >+ (WebCore::AnimationTimeline::updateCSSAnimationsForElement): We rename "oldStyle" to "currentStyle" to align with the naming used by updateCSSAnimationsForElement(). >+ We also remove an initial check that has been pushed up to Style::TreeResolver::createAnimatedElementUpdate(). >+ (WebCore::propertyInStyleMatchesValueForTransitionInMap): When running the steps mandated by the spec we often need to check whether a given property has a transition >+ in an AnimationList that matches the value used in a given RenderStyle. >+ (WebCore::transitionCombinedDuration): We need to compute the combined duration twice while running the steps mandated by the spec, so we have a dedicated utility. >+ (WebCore::transitionMatchesProperty): New utility that indicates whether a WebCore::Animation matches a given property, by virtue of targeting it directly, targeting >+ a shorthand for which this property is a longhand, or targeting "all". >+ (WebCore::AnimationTimeline::updateCSSTransitionsForElement): This is where all of the new implementation for starting transitions happens. We implement the steps >+ as they appear in the spec. >+ (WebCore::shouldBackingAnimationBeConsideredForCSSTransition): Deleted. >+ * animation/AnimationTimeline.h: >+ * animation/CSSAnimation.cpp: >+ (WebCore::CSSAnimation::syncPropertiesWithBackingAnimation): Since only CSS Animations respect the delay and duration values as parsed directly in a WebCore:Animation >+ object, we move code that was previously in DeclarativeAnimation::syncPropertiesWithBackingAnimation to this method. CSS Transitions set those values based on the >+ delay and duration parameters passed to CSSTransition::create() and computed in AnimationTimeline::updateCSSTransitionsForElement(). >+ * animation/CSSTransition.cpp: >+ (WebCore::CSSTransition::create): Since the transition's delay and duration is computed in AnimationTimeline::updateCSSTransitionsForElement(), we now require them >+ to be passed when creating a CSSTransition and pass those to the new setTimingProperties() function. We also expect a target style and reversing-adjusted start style, >+ as well as a reversing-shortening factor. >+ (WebCore::CSSTransition::CSSTransition): >+ (WebCore::CSSTransition::resolve): We need to be able to query the last style computed by a call to resolve() from AnimationTimeline::updateCSSTransitionsForElement(), >+ we subclass this newly-virtual WebAnimation method and clone the style after we blended the property targeted by this transition. >+ (WebCore::CSSTransition::setTimingProperties): Set the transition delay and duration as provided in the call to create(). >+ (WebCore::CSSTransition::canBeListed const): Fix a crash that was found while working on this bug where we could access a null effect. >+ (WebCore::CSSTransition::initialize): Deleted. >+ (WebCore::CSSTransition::matchesBackingAnimationAndStyles const): Deleted. >+ * animation/CSSTransition.h: >+ * animation/DeclarativeAnimation.cpp: >+ (WebCore::DeclarativeAnimation::syncPropertiesWithBackingAnimation): This virtual method now has an empty definition since the timing properties are now only set >+ for CSSAnimation. >+ * animation/KeyframeEffectReadOnly.cpp: >+ (WebCore::KeyframeEffectReadOnly::stylesWouldYieldNewCSSTransitionsBlendingKeyframes const): Deleted. >+ * animation/KeyframeEffectReadOnly.h: >+ * animation/WebAnimation.h: >+ * page/animation/CSSPropertyAnimation.cpp: >+ (WebCore::AnimationPropertyWrapperBase::canInterpolate const): Since we need to be able to determine whether some property values can be interpolated, we add a new >+ canInterpolate() method to the base wrapper class so the cases where we can't interpolate values (length with an "auto" type) may return false. >+ (WebCore::LengthPropertyWrapper::LengthPropertyWrapper): Lengths can only be interpolated if both the start and end values are not "auto". >+ (WebCore::LengthVariantPropertyWrapper::LengthVariantPropertyWrapper): >+ (WebCore::CSSPropertyAnimationWrapperMap::CSSPropertyAnimationWrapperMap): >+ (WebCore::CSSPropertyAnimation::canPropertyBeInterpolated): >+ * page/animation/CSSPropertyAnimation.h: >+ * style/StyleTreeResolver.cpp: >+ (WebCore::Style::TreeResolver::createAnimatedElementUpdate): Move a check found in both updateCSSAnimationsForElement() and updateCSSTransitionsForElement() to their >+ shared call site. >+ > 2018-06-18 Tomas Popela <tpopela@redhat.com> > > Properly check the sscanf return valua >diff --git a/Source/WebCore/animation/AnimationTimeline.cpp b/Source/WebCore/animation/AnimationTimeline.cpp >index 7ed02ce2b677b0000665a34754f52b09d2ef9ad0..0c0e10db44df6adfa82515865d9635bbe7f48537 100644 >--- a/Source/WebCore/animation/AnimationTimeline.cpp >+++ b/Source/WebCore/animation/AnimationTimeline.cpp >@@ -38,6 +38,7 @@ > #include "KeyframeEffectReadOnly.h" > #include "RenderStyle.h" > #include "RenderView.h" >+#include "StylePropertyShorthand.h" > #include "WebAnimationUtilities.h" > #include <wtf/text/TextStream.h> > #include <wtf/text/WTFString.h> >@@ -95,10 +96,24 @@ void AnimationTimeline::animationWasAddedToElement(WebAnimation& animation, Elem > }).iterator->value.add(&animation); > } > >+static inline bool removeCSSTransitionFromMap(CSSTransition& transition, Element& element, HashMap<Element*, HashMap<CSSPropertyID, RefPtr<CSSTransition>>>& map) >+{ >+ auto iterator = map.find(&element); >+ if (iterator == map.end()) >+ return false; >+ >+ auto& cssTransitionsByProperty = iterator->value; >+ cssTransitionsByProperty.remove(transition.property()); >+ if (cssTransitionsByProperty.isEmpty()) >+ map.remove(&element); >+ return true; >+} >+ > void AnimationTimeline::animationWasRemovedFromElement(WebAnimation& animation, Element& element) > { >- // First, we clear this animation from one of the m_elementToCSSAnimationsMap, m_elementToCSSTransitionsMap >- // or m_elementToAnimationsMap map, whichever is relevant to this type of animation. >+ // First, we clear this animation from one of the m_elementToCSSAnimationsMap, m_elementToCSSTransitionsMap, >+ // m_elementToAnimationsMap or m_elementToCompletedCSSTransitionByCSSPropertyID map, whichever is relevant to >+ // this type of animation. > auto& map = relevantMapForAnimation(animation); > auto iterator = map.find(&element); > if (iterator == map.end()) >@@ -110,7 +125,7 @@ void AnimationTimeline::animationWasRemovedFromElement(WebAnimation& animation, > map.remove(iterator); > > // Now, if we're dealing with a declarative animation, we remove it from either the m_elementToCSSAnimationByName >- // or the m_elementToCSSTransitionByCSSPropertyID map, whichever is relevant to this type of animation. >+ // or the m_elementToRunningCSSTransitionByCSSPropertyID map, whichever is relevant to this type of animation. > if (is<CSSAnimation>(animation)) { > auto iterator = m_elementToCSSAnimationByName.find(&element); > if (iterator != m_elementToCSSAnimationByName.end()) { >@@ -121,14 +136,9 @@ void AnimationTimeline::animationWasRemovedFromElement(WebAnimation& animation, > m_elementToCSSAnimationByName.remove(&element); > } > } else if (is<CSSTransition>(animation)) { >- auto iterator = m_elementToCSSTransitionByCSSPropertyID.find(&element); >- if (iterator != m_elementToCSSTransitionByCSSPropertyID.end()) { >- auto& cssTransitionsByProperty = iterator->value; >- auto property = downcast<CSSTransition>(animation).property(); >- cssTransitionsByProperty.remove(property); >- if (cssTransitionsByProperty.isEmpty()) >- m_elementToCSSTransitionByCSSPropertyID.remove(&element); >- } >+ auto& transition = downcast<CSSTransition>(animation); >+ if (!removeCSSTransitionFromMap(transition, element, m_elementToRunningCSSTransitionByCSSPropertyID)) >+ removeCSSTransitionFromMap(transition, element, m_elementToCompletedCSSTransitionByCSSPropertyID); > } > } > >@@ -158,16 +168,10 @@ void AnimationTimeline::removeAnimationsForElement(Element& element) > } > } > >-void AnimationTimeline::updateCSSAnimationsForElement(Element& element, const RenderStyle& newStyle, const RenderStyle* oldStyle) >+void AnimationTimeline::updateCSSAnimationsForElement(Element& element, const RenderStyle* currentStyle, const RenderStyle& afterChangeStyle) > { >- if (element.document().pageCacheState() != Document::NotInPageCache) >- return; >- >- if (element.document().renderView()->printing()) >- return; >- > // In case this element is newly getting a "display: none" we need to cancel all of its animations and disregard new ones. >- if (oldStyle && oldStyle->hasAnimations() && oldStyle->display() != DisplayType::None && newStyle.display() == DisplayType::None) { >+ if (currentStyle && currentStyle->hasAnimations() && currentStyle->display() != DisplayType::None && afterChangeStyle.display() == DisplayType::None) { > if (m_elementToCSSAnimationByName.contains(&element)) { > for (const auto& cssAnimationsByNameMapItem : m_elementToCSSAnimationByName.take(&element)) > cancelOrRemoveDeclarativeAnimation(cssAnimationsByNameMapItem.value); >@@ -175,13 +179,13 @@ void AnimationTimeline::updateCSSAnimationsForElement(Element& element, const Re > return; > } > >- if (oldStyle && oldStyle->hasAnimations() && newStyle.hasAnimations() && *(oldStyle->animations()) == *(newStyle.animations())) >+ if (currentStyle && currentStyle->hasAnimations() && afterChangeStyle.hasAnimations() && *(currentStyle->animations()) == *(afterChangeStyle.animations())) > return; > > // First, compile the list of animation names that were applied to this element up to this point. > HashSet<String> namesOfPreviousAnimations; >- if (oldStyle && oldStyle->hasAnimations()) { >- auto* previousAnimations = oldStyle->animations(); >+ if (currentStyle && currentStyle->hasAnimations()) { >+ auto* previousAnimations = currentStyle->animations(); > for (size_t i = 0; i < previousAnimations->size(); ++i) { > auto& previousAnimation = previousAnimations->animation(i); > if (previousAnimation.isValidAnimation()) >@@ -194,7 +198,7 @@ void AnimationTimeline::updateCSSAnimationsForElement(Element& element, const Re > return HashMap<String, RefPtr<CSSAnimation>> { }; > }).iterator->value; > >- if (auto* currentAnimations = newStyle.animations()) { >+ if (auto* currentAnimations = afterChangeStyle.animations()) { > for (size_t i = 0; i < currentAnimations->size(); ++i) { > auto& currentAnimation = currentAnimations->animation(i); > auto& name = currentAnimation.name(); >@@ -205,7 +209,7 @@ void AnimationTimeline::updateCSSAnimationsForElement(Element& element, const Re > cssAnimationsByName.get(name)->setBackingAnimation(currentAnimation); > } else if (currentAnimation.isValidAnimation()) { > // Otherwise we are dealing with a new animation name and must create a CSSAnimation for it. >- cssAnimationsByName.set(name, CSSAnimation::create(element, currentAnimation, oldStyle, newStyle)); >+ cssAnimationsByName.set(name, CSSAnimation::create(element, currentAnimation, currentStyle, afterChangeStyle)); > } > // Remove the name of this animation from our list since it's now known to be current. > namesOfPreviousAnimations.remove(name); >@@ -233,109 +237,183 @@ RefPtr<WebAnimation> AnimationTimeline::cssAnimationForElementAndProperty(Elemen > return matchingAnimation; > } > >-static bool shouldBackingAnimationBeConsideredForCSSTransition(const Animation& backingAnimation) >+static bool propertyInStyleMatchesValueForTransitionInMap(CSSPropertyID property, const RenderStyle& style, HashMap<CSSPropertyID, RefPtr<CSSTransition>>& transitions) > { >- auto mode = backingAnimation.animationMode(); >+ 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.animationMode(); > if (mode == Animation::AnimateNone || mode == Animation::AnimateUnknownProperty) > return false; >- if (mode == Animation::AnimateSingleProperty && backingAnimation.property() == CSSPropertyInvalid) >- return false; >+ if (mode == Animation::AnimateSingleProperty) { >+ auto transitionProperty = transition.property(); >+ if (transitionProperty != property) { >+ auto shorthand = shorthandForProperty(transitionProperty); >+ for (size_t i = 0; i < shorthand.length(); ++i) { >+ if (shorthand.properties()[i] == property) >+ return true; >+ } >+ return false; >+ } >+ } > return true; > } > >-void AnimationTimeline::updateCSSTransitionsForElement(Element& element, const RenderStyle& newStyle, const RenderStyle* oldStyle) >+void AnimationTimeline::updateCSSTransitionsForElement(Element& element, const RenderStyle& currentStyle, const RenderStyle& afterChangeStyle) > { >- if (element.document().pageCacheState() != Document::NotInPageCache) >- return; >- >- if (element.document().renderView()->printing()) >- return; >- >- // In case this element is newly getting a "display: none" we need to cancel all of its animations and disregard new ones. >- if (oldStyle && oldStyle->hasTransitions() && oldStyle->display() != DisplayType::None && newStyle.display() == DisplayType::None) { >- if (m_elementToCSSTransitionByCSSPropertyID.contains(&element)) { >- for (const auto& cssTransitionsByCSSPropertyIDMapItem : m_elementToCSSTransitionByCSSPropertyID.take(&element)) >+ // 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 && afterChangeStyle.display() == DisplayType::None) { >+ if (m_elementToRunningCSSTransitionByCSSPropertyID.contains(&element)) { >+ for (const auto& cssTransitionsByCSSPropertyIDMapItem : m_elementToRunningCSSTransitionByCSSPropertyID.take(&element)) > cancelOrRemoveDeclarativeAnimation(cssTransitionsByCSSPropertyIDMapItem.value); > } > return; > } > >- // Create or get the CSSTransitions by CSS property name map for this element. >- auto& cssTransitionsByProperty = m_elementToCSSTransitionByCSSPropertyID.ensure(&element, [] { >+ // Section 3 "Starting of transitions" from the CSS Transitions Level 1 specification. >+ // https://drafts.csswg.org/css-transitions-1/#starting >+ >+ auto& runningTransitionsByProperty = m_elementToRunningCSSTransitionByCSSPropertyID.ensure(&element, [] { > return HashMap<CSSPropertyID, RefPtr<CSSTransition>> { }; > }).iterator->value; > >- // First, compile the list of backing animations and properties that were applied to this element up to this point. >- auto previousProperties = copyToVector(cssTransitionsByProperty.keys()); >- HashSet<const Animation*> previousBackingAnimations; >- if (oldStyle && oldStyle->hasTransitions()) { >- auto* previousTransitions = oldStyle->transitions(); >- for (size_t i = 0; i < previousTransitions->size(); ++i) { >- auto& backingAnimation = previousTransitions->animation(i); >- if (shouldBackingAnimationBeConsideredForCSSTransition(backingAnimation)) >- previousBackingAnimations.add(&backingAnimation); >- } >- } >+ auto& completedTransitionsByProperty = m_elementToCompletedCSSTransitionByCSSPropertyID.ensure(&element, [] { >+ return HashMap<CSSPropertyID, RefPtr<CSSTransition>> { }; >+ }).iterator->value; > >- if (auto* currentTransitions = newStyle.transitions()) { >- for (size_t i = 0; i < currentTransitions->size(); ++i) { >- auto& backingAnimation = currentTransitions->animation(i); >- if (!shouldBackingAnimationBeConsideredForCSSTransition(backingAnimation)) >- continue; >- auto property = backingAnimation.property(); >- bool transitionsAllProperties = backingAnimation.animationMode() == Animation::AnimateAll; >- auto numberOfProperties = CSSPropertyAnimation::getNumProperties(); >- // In the "transition-property: all" case, where the animation's mode is set to AnimateAll, >- // the property will be set to CSSPropertyInvalid and we need to iterate over all known >- // CSS properties and see if they have mis-matching values in the old and new styles, which >- // means they should have a CSSTransition created for them. >- // We implement a single loop which handles the "all" case and the specified property case >- // by using the pre-set property above in the specified property case and breaking out of >- // the loop after the first complete iteration. >- for (int propertyIndex = 0; propertyIndex < numberOfProperties; ++propertyIndex) { >- if (transitionsAllProperties) { >- bool isShorthand; >- property = CSSPropertyAnimation::getPropertyAtIndex(propertyIndex, isShorthand); >- if (isShorthand) >- continue; >- } else if (propertyIndex) { >- // We only go once through this loop if we are transitioning a single property. >- break; >- } >- >- previousProperties.removeFirst(property); >- // We've found a backing animation that we didn't know about for a valid property. >- if (!previousBackingAnimations.contains(&backingAnimation)) { >- // If we already had a CSSTransition for this property, check whether its timing properties match the current backing >- // animation's properties and whether its blending keyframes match the old and new styles. If they do, move on to the >- // next transition, otherwise delete the previous CSSTransition object, and create a new one. >- if (cssTransitionsByProperty.contains(property)) { >- if (cssTransitionsByProperty.get(property)->matchesBackingAnimationAndStyles(backingAnimation, oldStyle, newStyle)) >- continue; >- removeAnimation(cssTransitionsByProperty.take(property).releaseNonNull()); >- } >- // Now we can create a new CSSTransition with the new backing animation provided it has a valid >- // duration and the from and to values are distinct. >- if ((backingAnimation.duration() || backingAnimation.delay() > 0) && oldStyle) { >- auto existingAnimation = cssAnimationForElementAndProperty(element, property); >- const auto* fromStyle = existingAnimation ? &downcast<CSSAnimation>(existingAnimation.get())->unanimatedStyle() : oldStyle; >- if (!CSSPropertyAnimation::propertiesEqual(property, fromStyle, &newStyle)) >- cssTransitionsByProperty.set(property, CSSTransition::create(element, property, backingAnimation, fromStyle, newStyle)); >- } >- } >+ auto numberOfProperties = CSSPropertyAnimation::getNumProperties(); >+ for (int propertyIndex = 0; propertyIndex < numberOfProperties; ++propertyIndex) { >+ bool isShorthand; >+ auto property = CSSPropertyAnimation::getPropertyAtIndex(propertyIndex, isShorthand); >+ if (isShorthand) >+ continue; >+ >+ const Animation* matchingBackingAnimation = nullptr; >+ if (auto* transitions = afterChangeStyle.transitions()) { >+ for (size_t i = 0; i < transitions->size(); ++i) { >+ auto& backingAnimation = transitions->animation(i); >+ if (transitionMatchesProperty(backingAnimation, property)) >+ matchingBackingAnimation = &backingAnimation; > } > } >- } > >- // Remaining properties are no longer current and must be removed. >- for (const auto transitionPropertyToRemove : previousProperties) { >- if (cssTransitionsByProperty.contains(transitionPropertyToRemove)) >- cancelOrRemoveDeclarativeAnimation(cssTransitionsByProperty.take(transitionPropertyToRemove)); >+ // 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 existingAnimation = cssAnimationForElementAndProperty(element, property); >+ const auto& beforeChangeStyle = existingAnimation ? downcast<CSSAnimation>(existingAnimation.get())->unanimatedStyle() : currentStyle; >+ >+ if (!runningTransitionsByProperty.contains(property) >+ && !CSSPropertyAnimation::propertiesEqual(property, &beforeChangeStyle, &afterChangeStyle) >+ && CSSPropertyAnimation::canPropertyBeInterpolated(property, &beforeChangeStyle, &afterChangeStyle) >+ && !propertyInStyleMatchesValueForTransitionInMap(property, afterChangeStyle, completedTransitionsByProperty) >+ && 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 >+ completedTransitionsByProperty.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; >+ runningTransitionsByProperty.set(property, CSSTransition::create(element, property, *matchingBackingAnimation, &beforeChangeStyle, afterChangeStyle, delay, duration, reversingAdjustedStartStyle, reversingShorteningFactor)); >+ } else if (completedTransitionsByProperty.contains(property) && !propertyInStyleMatchesValueForTransitionInMap(property, afterChangeStyle, completedTransitionsByProperty)) { >+ // 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. >+ completedTransitionsByProperty.remove(property); >+ } >+ >+ bool hasRunningTransition = runningTransitionsByProperty.contains(property); >+ if ((hasRunningTransition || completedTransitionsByProperty.contains(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) >+ runningTransitionsByProperty.take(property)->cancel(); >+ else >+ completedTransitionsByProperty.remove(property); >+ } >+ >+ if (matchingBackingAnimation && runningTransitionsByProperty.contains(property) && !propertyInStyleMatchesValueForTransitionInMap(property, afterChangeStyle, runningTransitionsByProperty)) { >+ auto previouslyRunningTransition = runningTransitionsByProperty.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, ¤tStyle, &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->cancel(); >+ } 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->cancel(); >+ } 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->cancel(); >+ >+ // 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()) >+ transformedProgress = effect->iterationProgress().value_or(transformedProgress); >+ 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; >+ runningTransitionsByProperty.set(property, CSSTransition::create(element, property, *matchingBackingAnimation, &previouslyRunningTransitionCurrentStyle, afterChangeStyle, delay, duration, reversingAdjustedStartStyle, reversingShorteningFactor)); >+ } else { >+ // 4. Otherwise, implementations must cancel the running transition >+ previouslyRunningTransition->cancel(); >+ >+ // 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; >+ runningTransitionsByProperty.set(property, CSSTransition::create(element, property, *matchingBackingAnimation, &previouslyRunningTransitionCurrentStyle, afterChangeStyle, delay, duration, reversingAdjustedStartStyle, reversingShorteningFactor)); >+ } >+ } > } > >- // Remove the map of CSSTransitions by property for this element if it's now empty. >- if (cssTransitionsByProperty.isEmpty()) >- m_elementToCSSTransitionByCSSPropertyID.remove(&element); > } > > void AnimationTimeline::cancelOrRemoveDeclarativeAnimation(RefPtr<DeclarativeAnimation> animation) >diff --git a/Source/WebCore/animation/AnimationTimeline.h b/Source/WebCore/animation/AnimationTimeline.h >index 3680cb0ef697b819fc42824f3810a775ecd34e0d..fe9a7c6d40f8f30fc93ad5d7e5024b51d56982de 100644 >--- a/Source/WebCore/animation/AnimationTimeline.h >+++ b/Source/WebCore/animation/AnimationTimeline.h >@@ -63,8 +63,8 @@ public: > void animationWasAddedToElement(WebAnimation&, Element&); > void animationWasRemovedFromElement(WebAnimation&, Element&); > >- void updateCSSAnimationsForElement(Element&, const RenderStyle& newStyle, const RenderStyle* oldStyle); >- void updateCSSTransitionsForElement(Element&, const RenderStyle& newStyle, const RenderStyle* oldStyle); >+ void updateCSSAnimationsForElement(Element&, const RenderStyle* currentStyle, const RenderStyle& afterChangeStyle); >+ void updateCSSTransitionsForElement(Element&, const RenderStyle& currentStyle, const RenderStyle& afterChangeStyle); > > virtual ~AnimationTimeline(); > >@@ -96,7 +96,8 @@ private: > ListHashSet<RefPtr<WebAnimation>> m_animations; > > HashMap<Element*, HashMap<String, RefPtr<CSSAnimation>>> m_elementToCSSAnimationByName; >- HashMap<Element*, HashMap<CSSPropertyID, RefPtr<CSSTransition>>> m_elementToCSSTransitionByCSSPropertyID; >+ HashMap<Element*, HashMap<CSSPropertyID, RefPtr<CSSTransition>>> m_elementToRunningCSSTransitionByCSSPropertyID; >+ HashMap<Element*, HashMap<CSSPropertyID, RefPtr<CSSTransition>>> m_elementToCompletedCSSTransitionByCSSPropertyID; > }; > > } // namespace WebCore >diff --git a/Source/WebCore/animation/CSSAnimation.cpp b/Source/WebCore/animation/CSSAnimation.cpp >index 2f8cdc433659684ad091ae77f79f7075c5bf2074..1b65f513876a74a946a00179d707e0f250ab1613 100644 >--- a/Source/WebCore/animation/CSSAnimation.cpp >+++ b/Source/WebCore/animation/CSSAnimation.cpp >@@ -87,10 +87,13 @@ void CSSAnimation::syncPropertiesWithBackingAnimation() > auto iterationCount = animation.iterationCount(); > timing->setIterations(iterationCount == Animation::IterationCountInfinite ? std::numeric_limits<double>::infinity() : iterationCount); > >+ timing->setDelay(Seconds(animation.delay())); >+ timing->setIterationDuration(Seconds(animation.duration())); >+ > // Synchronize the play state >- if (backingAnimation().playState() == AnimationPlayState::Playing && playState() == WebAnimation::PlayState::Paused) >+ if (animation.playState() == AnimationPlayState::Playing && playState() == WebAnimation::PlayState::Paused) > play(); >- else if (backingAnimation().playState() == AnimationPlayState::Paused && playState() == WebAnimation::PlayState::Running) >+ else if (animation.playState() == AnimationPlayState::Paused && playState() == WebAnimation::PlayState::Running) > pause(); > > unsuspendEffectInvalidation(); >diff --git a/Source/WebCore/animation/CSSTransition.cpp b/Source/WebCore/animation/CSSTransition.cpp >index d93e6ffc7bfcc4566d03bdad72cbc38b25edc222..30f2262c32a7a8f26fd975cd07a2467a4a410db3 100644 >--- a/Source/WebCore/animation/CSSTransition.cpp >+++ b/Source/WebCore/animation/CSSTransition.cpp >@@ -32,45 +32,52 @@ > > namespace WebCore { > >-Ref<CSSTransition> CSSTransition::create(Element& target, CSSPropertyID property, const Animation& backingAnimation, const RenderStyle* oldStyle, const RenderStyle& newStyle) >+Ref<CSSTransition> CSSTransition::create(Element& target, CSSPropertyID property, const Animation& backingAnimation, const RenderStyle* oldStyle, const RenderStyle& newStyle, Seconds delay, Seconds duration, const RenderStyle& reversingAdjustedStartStyle, double reversingShorteningFactor) > { >- auto result = adoptRef(*new CSSTransition(target, property, backingAnimation)); >+ auto result = adoptRef(*new CSSTransition(target, property, backingAnimation, newStyle, reversingAdjustedStartStyle, reversingShorteningFactor)); > result->initialize(target, oldStyle, newStyle); >+ result->setTimingProperties(delay, duration); > return result; > } > >-CSSTransition::CSSTransition(Element& element, CSSPropertyID property, const Animation& backingAnimation) >+CSSTransition::CSSTransition(Element& element, CSSPropertyID property, const Animation& backingAnimation, const RenderStyle& targetStyle, const RenderStyle& reversingAdjustedStartStyle, double reversingShorteningFactor) > : DeclarativeAnimation(element, backingAnimation) > , m_property(property) >+ , m_targetStyle(RenderStyle::clonePtr(targetStyle)) >+ , m_reversingAdjustedStartStyle(RenderStyle::clonePtr(reversingAdjustedStartStyle)) >+ , m_reversingShorteningFactor(reversingShorteningFactor) > { > } > >-void CSSTransition::initialize(const Element& target, const RenderStyle* oldStyle, const RenderStyle& newStyle) >+void CSSTransition::resolve(RenderStyle& targetStyle) > { >- DeclarativeAnimation::initialize(target, oldStyle, newStyle); >+ DeclarativeAnimation::resolve(targetStyle); >+ m_currentStyle = RenderStyle::clonePtr(targetStyle); >+} > >+void CSSTransition::setTimingProperties(Seconds delay, Seconds duration) >+{ > suspendEffectInvalidation(); > >+ auto* timing = effect()->timing(); > // In order for CSS Transitions to be seeked backwards, they need to have their fill mode set to backwards > // such that the original CSS value applied prior to the transition is used for a negative current time. >- effect()->timing()->setFill(FillMode::Backwards); >+ >+ timing->setFill(FillMode::Backwards); >+ timing->setDelay(delay); >+ timing->setIterationDuration(duration); > > unsuspendEffectInvalidation(); > } > >-bool CSSTransition::matchesBackingAnimationAndStyles(const Animation& newBackingAnimation, const RenderStyle* oldStyle, const RenderStyle& newStyle) const >-{ >- // See if the animations match, excluding the property since we can move from an "all" transition to an explicit property transition. >- bool backingAnimationsMatch = backingAnimation().animationsMatch(newBackingAnimation, false); >- if (!oldStyle || !effect()) >- return backingAnimationsMatch; >- return backingAnimationsMatch && !downcast<KeyframeEffectReadOnly>(effect())->stylesWouldYieldNewCSSTransitionsBlendingKeyframes(*oldStyle, newStyle); >-} >- > bool CSSTransition::canBeListed() const > { >- if (!downcast<KeyframeEffectReadOnly>(effect())->hasBlendingKeyframes()) >- return false; >+ if (auto* transitionEffect = effect()) { >+ if (is<KeyframeEffectReadOnly>(transitionEffect)) { >+ if (!downcast<KeyframeEffectReadOnly>(effect())->hasBlendingKeyframes()) >+ return false; >+ } >+ } > return WebAnimation::canBeListed(); > } > >diff --git a/Source/WebCore/animation/CSSTransition.h b/Source/WebCore/animation/CSSTransition.h >index 50dda8b097acdc5ae436a6c72d2d2b1413e37c42..a933313f18379d05e0f96f9f14130bcef8c88c5e 100644 >--- a/Source/WebCore/animation/CSSTransition.h >+++ b/Source/WebCore/animation/CSSTransition.h >@@ -37,23 +37,29 @@ class RenderStyle; > > class CSSTransition final : public DeclarativeAnimation { > public: >- static Ref<CSSTransition> create(Element&, CSSPropertyID, const Animation&, const RenderStyle* oldStyle, const RenderStyle& newStyle); >+ static Ref<CSSTransition> create(Element&, CSSPropertyID, const Animation&, const RenderStyle* oldStyle, const RenderStyle& newStyle, Seconds delay, Seconds duration, const RenderStyle& reversingAdjustedStartStyle, double); > ~CSSTransition() = default; > > bool isCSSTransition() const override { return true; } > String transitionProperty() const { return getPropertyNameString(m_property); } > CSSPropertyID property() const { return m_property; } >+ const RenderStyle& targetStyle() const { return *m_targetStyle; } >+ const RenderStyle& currentStyle() const { return *m_currentStyle; } >+ const RenderStyle& reversingAdjustedStartStyle() const { return *m_reversingAdjustedStartStyle; } >+ double reversingShorteningFactor() const { return m_reversingShorteningFactor; } > >- bool matchesBackingAnimationAndStyles(const Animation&, const RenderStyle* oldStyle, const RenderStyle& newStyle) const; > bool canBeListed() const final; >- >-protected: >- void initialize(const Element&, const RenderStyle* oldStyle, const RenderStyle& newStyle) final; >+ void resolve(RenderStyle&) final; > > private: >- CSSTransition(Element&, CSSPropertyID, const Animation&); >+ CSSTransition(Element&, CSSPropertyID, const Animation&, const RenderStyle& targetStyle, const RenderStyle& reversingAdjustedStartStyle, double); >+ void setTimingProperties(Seconds delay, Seconds duration); > > CSSPropertyID m_property; >+ std::unique_ptr<RenderStyle> m_targetStyle; >+ std::unique_ptr<RenderStyle> m_currentStyle; >+ std::unique_ptr<RenderStyle> m_reversingAdjustedStartStyle; >+ double m_reversingShorteningFactor; > > }; > >diff --git a/Source/WebCore/animation/DeclarativeAnimation.cpp b/Source/WebCore/animation/DeclarativeAnimation.cpp >index 646b0eb50f5eeb95f08a3728cc48a04547340857..b944a2a0c69bf0e2444b094fd80d50b7ac7fcbc2 100644 >--- a/Source/WebCore/animation/DeclarativeAnimation.cpp >+++ b/Source/WebCore/animation/DeclarativeAnimation.cpp >@@ -82,13 +82,6 @@ void DeclarativeAnimation::initialize(const Element& target, const RenderStyle* > > void DeclarativeAnimation::syncPropertiesWithBackingAnimation() > { >- suspendEffectInvalidation(); >- >- auto* timing = effect()->timing(); >- timing->setDelay(Seconds(m_backingAnimation->delay())); >- timing->setIterationDuration(Seconds(m_backingAnimation->duration())); >- >- unsuspendEffectInvalidation(); > } > > void DeclarativeAnimation::setTimeline(RefPtr<AnimationTimeline>&& newTimeline) >diff --git a/Source/WebCore/animation/KeyframeEffectReadOnly.cpp b/Source/WebCore/animation/KeyframeEffectReadOnly.cpp >index 8ba7b6c1764f0322d7ded656255cbb3e12fbd5dd..96396956a9d007549bcb721c870720991eda31ad 100644 >--- a/Source/WebCore/animation/KeyframeEffectReadOnly.cpp >+++ b/Source/WebCore/animation/KeyframeEffectReadOnly.cpp >@@ -877,25 +877,6 @@ void KeyframeEffectReadOnly::computeCSSTransitionBlendingKeyframes(const RenderS > setBlendingKeyframes(keyframeList); > } > >-bool KeyframeEffectReadOnly::stylesWouldYieldNewCSSTransitionsBlendingKeyframes(const RenderStyle& oldStyle, const RenderStyle& newStyle) const >-{ >- ASSERT(is<CSSTransition>(animation())); >- >- // We don't yet have blending keyframes to compare with, so these wouldn't be new keyframes, but the fisrt ones. >- if (!hasBlendingKeyframes()) >- return false; >- >- auto property = downcast<CSSTransition>(animation())->property(); >- >- // There cannot be new keyframes if the start and to values are the same. >- if (CSSPropertyAnimation::propertiesEqual(property, &oldStyle, &newStyle)) >- return false; >- >- // Otherwise, we would create new blending keyframes provided the current end keyframe holds a different >- // value than the new end style for this property. >- return !CSSPropertyAnimation::propertiesEqual(property, m_blendingKeyframes[1].style(), &newStyle); >-} >- > void KeyframeEffectReadOnly::computedNeedsForcedLayout() > { > m_needsForcedLayout = false; >diff --git a/Source/WebCore/animation/KeyframeEffectReadOnly.h b/Source/WebCore/animation/KeyframeEffectReadOnly.h >index 8acba015b4a877075650166834c71b7237bf8404..17c3964bf1cc2cfdcd53559cdafb47d0c84f5a32 100644 >--- a/Source/WebCore/animation/KeyframeEffectReadOnly.h >+++ b/Source/WebCore/animation/KeyframeEffectReadOnly.h >@@ -114,7 +114,6 @@ public: > bool colorFilterFunctionListsMatch() const override { return m_colorFilterFunctionListsMatch; } > > void computeDeclarativeAnimationBlendingKeyframes(const RenderStyle* oldStyle, const RenderStyle& newStyle); >- bool stylesWouldYieldNewCSSTransitionsBlendingKeyframes(const RenderStyle& oldStyle, const RenderStyle& newStyle) const; > bool hasBlendingKeyframes() const { return m_blendingKeyframes.size(); } > const HashSet<CSSPropertyID>& animatedProperties() const { return m_blendingKeyframes.properties(); } > >diff --git a/Source/WebCore/animation/WebAnimation.h b/Source/WebCore/animation/WebAnimation.h >index baa42f24272b0c535efde3b5ae64cfd5fad5e501..cb8db1d2573db6bfd279325f8dd38d171c57cdaf 100644 >--- a/Source/WebCore/animation/WebAnimation.h >+++ b/Source/WebCore/animation/WebAnimation.h >@@ -99,7 +99,7 @@ public: > ExceptionOr<void> reverse(); > > Seconds timeToNextRequiredTick() const; >- void resolve(RenderStyle&); >+ virtual void resolve(RenderStyle&); > void effectTargetDidChange(Element* previousTarget, Element* newTarget); > void acceleratedStateDidChange(); > void applyPendingAcceleratedActions(); >diff --git a/Source/WebCore/page/animation/CSSPropertyAnimation.cpp b/Source/WebCore/page/animation/CSSPropertyAnimation.cpp >index 3fb9fe6fb2d83d4ca6cb4074dc043cf73955e463..b3f0c5a1df075702818145967d38b42aad380201 100644 >--- a/Source/WebCore/page/animation/CSSPropertyAnimation.cpp >+++ b/Source/WebCore/page/animation/CSSPropertyAnimation.cpp >@@ -426,6 +426,7 @@ public: > > virtual bool isShorthandWrapper() const { return false; } > virtual bool equals(const RenderStyle* a, const RenderStyle* b) const = 0; >+ virtual bool canInterpolate(const RenderStyle*, const RenderStyle*) const { return true; } > virtual void blend(const CSSPropertyBlendingClient*, RenderStyle*, const RenderStyle*, const RenderStyle*, double) const = 0; > > #if !LOG_DISABLED >@@ -513,11 +514,34 @@ protected: > void (RenderStyle::*m_setter)(RefPtr<T>&&); > }; > >+class LengthPropertyWrapper : public PropertyWrapperGetter<const Length&> { >+ WTF_MAKE_FAST_ALLOCATED; >+public: >+ LengthPropertyWrapper(CSSPropertyID prop, const Length& (RenderStyle::*getter)() const, void (RenderStyle::*setter)(Length&&)) >+ : PropertyWrapperGetter<const Length&>(prop, getter) >+ , m_setter(setter) >+ { >+ } >+ >+ bool canInterpolate(const RenderStyle* a, const RenderStyle* b) const override >+ { >+ return !(a->*PropertyWrapperGetter<const Length&>::m_getter)().isAuto() && !(b->*PropertyWrapperGetter<const Length&>::m_getter)().isAuto(); >+ } >+ >+ void blend(const CSSPropertyBlendingClient* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const override >+ { >+ (dst->*m_setter)(blendFunc(anim, (a->*PropertyWrapperGetter<const Length&>::m_getter)(), (b->*PropertyWrapperGetter<const Length&>::m_getter)(), progress)); >+ } >+ >+protected: >+ void (RenderStyle::*m_setter)(Length&&); >+}; >+ > template <typename T> >-class LengthPropertyWrapper : public PropertyWrapperGetter<const T&> { >+class LengthVariantPropertyWrapper : public PropertyWrapperGetter<const T&> { > WTF_MAKE_FAST_ALLOCATED; > public: >- LengthPropertyWrapper(CSSPropertyID prop, const T& (RenderStyle::*getter)() const, void (RenderStyle::*setter)(T&&)) >+ LengthVariantPropertyWrapper(CSSPropertyID prop, const T& (RenderStyle::*getter)() const, void (RenderStyle::*setter)(T&&)) > : PropertyWrapperGetter<const T&>(prop, getter) > , m_setter(setter) > { >@@ -1469,18 +1493,18 @@ CSSPropertyAnimationWrapperMap::CSSPropertyAnimationWrapperMap() > { > // build the list of property wrappers to do the comparisons and blends > AnimationPropertyWrapperBase* animatableLonghandPropertyWrappers[] = { >- new LengthPropertyWrapper<Length>(CSSPropertyLeft, &RenderStyle::left, &RenderStyle::setLeft), >- new LengthPropertyWrapper<Length>(CSSPropertyRight, &RenderStyle::right, &RenderStyle::setRight), >- new LengthPropertyWrapper<Length>(CSSPropertyTop, &RenderStyle::top, &RenderStyle::setTop), >- new LengthPropertyWrapper<Length>(CSSPropertyBottom, &RenderStyle::bottom, &RenderStyle::setBottom), >+ new LengthPropertyWrapper(CSSPropertyLeft, &RenderStyle::left, &RenderStyle::setLeft), >+ new LengthPropertyWrapper(CSSPropertyRight, &RenderStyle::right, &RenderStyle::setRight), >+ new LengthPropertyWrapper(CSSPropertyTop, &RenderStyle::top, &RenderStyle::setTop), >+ new LengthPropertyWrapper(CSSPropertyBottom, &RenderStyle::bottom, &RenderStyle::setBottom), > >- new LengthPropertyWrapper<Length>(CSSPropertyWidth, &RenderStyle::width, &RenderStyle::setWidth), >- new LengthPropertyWrapper<Length>(CSSPropertyMinWidth, &RenderStyle::minWidth, &RenderStyle::setMinWidth), >- new LengthPropertyWrapper<Length>(CSSPropertyMaxWidth, &RenderStyle::maxWidth, &RenderStyle::setMaxWidth), >+ new LengthPropertyWrapper(CSSPropertyWidth, &RenderStyle::width, &RenderStyle::setWidth), >+ new LengthPropertyWrapper(CSSPropertyMinWidth, &RenderStyle::minWidth, &RenderStyle::setMinWidth), >+ new LengthPropertyWrapper(CSSPropertyMaxWidth, &RenderStyle::maxWidth, &RenderStyle::setMaxWidth), > >- new LengthPropertyWrapper<Length>(CSSPropertyHeight, &RenderStyle::height, &RenderStyle::setHeight), >- new LengthPropertyWrapper<Length>(CSSPropertyMinHeight, &RenderStyle::minHeight, &RenderStyle::setMinHeight), >- new LengthPropertyWrapper<Length>(CSSPropertyMaxHeight, &RenderStyle::maxHeight, &RenderStyle::setMaxHeight), >+ new LengthPropertyWrapper(CSSPropertyHeight, &RenderStyle::height, &RenderStyle::setHeight), >+ new LengthPropertyWrapper(CSSPropertyMinHeight, &RenderStyle::minHeight, &RenderStyle::setMinHeight), >+ new LengthPropertyWrapper(CSSPropertyMaxHeight, &RenderStyle::maxHeight, &RenderStyle::setMaxHeight), > > new PropertyWrapperFlex(), > >@@ -1488,14 +1512,14 @@ CSSPropertyAnimationWrapperMap::CSSPropertyAnimationWrapperMap() > new PropertyWrapper<float>(CSSPropertyBorderRightWidth, &RenderStyle::borderRightWidth, &RenderStyle::setBorderRightWidth), > new PropertyWrapper<float>(CSSPropertyBorderTopWidth, &RenderStyle::borderTopWidth, &RenderStyle::setBorderTopWidth), > new PropertyWrapper<float>(CSSPropertyBorderBottomWidth, &RenderStyle::borderBottomWidth, &RenderStyle::setBorderBottomWidth), >- new LengthPropertyWrapper<Length>(CSSPropertyMarginLeft, &RenderStyle::marginLeft, &RenderStyle::setMarginLeft), >- new LengthPropertyWrapper<Length>(CSSPropertyMarginRight, &RenderStyle::marginRight, &RenderStyle::setMarginRight), >- new LengthPropertyWrapper<Length>(CSSPropertyMarginTop, &RenderStyle::marginTop, &RenderStyle::setMarginTop), >- new LengthPropertyWrapper<Length>(CSSPropertyMarginBottom, &RenderStyle::marginBottom, &RenderStyle::setMarginBottom), >- new LengthPropertyWrapper<Length>(CSSPropertyPaddingLeft, &RenderStyle::paddingLeft, &RenderStyle::setPaddingLeft), >- new LengthPropertyWrapper<Length>(CSSPropertyPaddingRight, &RenderStyle::paddingRight, &RenderStyle::setPaddingRight), >- new LengthPropertyWrapper<Length>(CSSPropertyPaddingTop, &RenderStyle::paddingTop, &RenderStyle::setPaddingTop), >- new LengthPropertyWrapper<Length>(CSSPropertyPaddingBottom, &RenderStyle::paddingBottom, &RenderStyle::setPaddingBottom), >+ new LengthPropertyWrapper(CSSPropertyMarginLeft, &RenderStyle::marginLeft, &RenderStyle::setMarginLeft), >+ new LengthPropertyWrapper(CSSPropertyMarginRight, &RenderStyle::marginRight, &RenderStyle::setMarginRight), >+ new LengthPropertyWrapper(CSSPropertyMarginTop, &RenderStyle::marginTop, &RenderStyle::setMarginTop), >+ new LengthPropertyWrapper(CSSPropertyMarginBottom, &RenderStyle::marginBottom, &RenderStyle::setMarginBottom), >+ new LengthPropertyWrapper(CSSPropertyPaddingLeft, &RenderStyle::paddingLeft, &RenderStyle::setPaddingLeft), >+ new LengthPropertyWrapper(CSSPropertyPaddingRight, &RenderStyle::paddingRight, &RenderStyle::setPaddingRight), >+ new LengthPropertyWrapper(CSSPropertyPaddingTop, &RenderStyle::paddingTop, &RenderStyle::setPaddingTop), >+ new LengthPropertyWrapper(CSSPropertyPaddingBottom, &RenderStyle::paddingBottom, &RenderStyle::setPaddingBottom), > > new PropertyWrapperVisitedAffectedColor(CSSPropertyCaretColor, &RenderStyle::caretColor, &RenderStyle::setCaretColor, &RenderStyle::visitedLinkCaretColor, &RenderStyle::setVisitedLinkCaretColor), > >@@ -1508,9 +1532,9 @@ CSSPropertyAnimationWrapperMap::CSSPropertyAnimationWrapperMap() > new StyleImagePropertyWrapper(CSSPropertyWebkitMaskImage, &RenderStyle::maskImage, &RenderStyle::setMaskImage), > > new StyleImagePropertyWrapper(CSSPropertyBorderImageSource, &RenderStyle::borderImageSource, &RenderStyle::setBorderImageSource), >- new LengthPropertyWrapper<LengthBox>(CSSPropertyBorderImageSlice, &RenderStyle::borderImageSlices, &RenderStyle::setBorderImageSlices), >- new LengthPropertyWrapper<LengthBox>(CSSPropertyBorderImageWidth, &RenderStyle::borderImageWidth, &RenderStyle::setBorderImageWidth), >- new LengthPropertyWrapper<LengthBox>(CSSPropertyBorderImageOutset, &RenderStyle::borderImageOutset, &RenderStyle::setBorderImageOutset), >+ new LengthVariantPropertyWrapper<LengthBox>(CSSPropertyBorderImageSlice, &RenderStyle::borderImageSlices, &RenderStyle::setBorderImageSlices), >+ new LengthVariantPropertyWrapper<LengthBox>(CSSPropertyBorderImageWidth, &RenderStyle::borderImageWidth, &RenderStyle::setBorderImageWidth), >+ new LengthVariantPropertyWrapper<LengthBox>(CSSPropertyBorderImageOutset, &RenderStyle::borderImageOutset, &RenderStyle::setBorderImageOutset), > > new StyleImagePropertyWrapper(CSSPropertyWebkitMaskBoxImageSource, &RenderStyle::maskBoxImageSource, &RenderStyle::setMaskBoxImageSource), > new PropertyWrapper<const NinePieceImage&>(CSSPropertyWebkitMaskBoxImage, &RenderStyle::maskBoxImage, &RenderStyle::setMaskBoxImage), >@@ -1526,8 +1550,8 @@ CSSPropertyAnimationWrapperMap::CSSPropertyAnimationWrapperMap() > > new PropertyWrapper<float>(CSSPropertyFontSize, &RenderStyle::computedFontSize, &RenderStyle::setFontSize), > new PropertyWrapper<unsigned short>(CSSPropertyColumnRuleWidth, &RenderStyle::columnRuleWidth, &RenderStyle::setColumnRuleWidth), >- new LengthPropertyWrapper<GapLength>(CSSPropertyColumnGap, &RenderStyle::columnGap, &RenderStyle::setColumnGap), >- new LengthPropertyWrapper<GapLength>(CSSPropertyRowGap, &RenderStyle::rowGap, &RenderStyle::setRowGap), >+ new LengthVariantPropertyWrapper<GapLength>(CSSPropertyColumnGap, &RenderStyle::columnGap, &RenderStyle::setColumnGap), >+ new LengthVariantPropertyWrapper<GapLength>(CSSPropertyRowGap, &RenderStyle::rowGap, &RenderStyle::setRowGap), > new PropertyWrapper<unsigned short>(CSSPropertyColumnCount, &RenderStyle::columnCount, &RenderStyle::setColumnCount), > new PropertyWrapper<float>(CSSPropertyColumnWidth, &RenderStyle::columnWidth, &RenderStyle::setColumnWidth), > new PropertyWrapper<float>(CSSPropertyWebkitBorderHorizontalSpacing, &RenderStyle::horizontalBorderSpacing, &RenderStyle::setHorizontalBorderSpacing), >@@ -1535,27 +1559,27 @@ CSSPropertyAnimationWrapperMap::CSSPropertyAnimationWrapperMap() > new PropertyWrapper<int>(CSSPropertyZIndex, &RenderStyle::zIndex, &RenderStyle::setZIndex), > new PropertyWrapper<short>(CSSPropertyOrphans, &RenderStyle::orphans, &RenderStyle::setOrphans), > new PropertyWrapper<short>(CSSPropertyWidows, &RenderStyle::widows, &RenderStyle::setWidows), >- new LengthPropertyWrapper<Length>(CSSPropertyLineHeight, &RenderStyle::specifiedLineHeight, &RenderStyle::setLineHeight), >+ new LengthPropertyWrapper(CSSPropertyLineHeight, &RenderStyle::specifiedLineHeight, &RenderStyle::setLineHeight), > new PropertyWrapper<float>(CSSPropertyOutlineOffset, &RenderStyle::outlineOffset, &RenderStyle::setOutlineOffset), > new PropertyWrapper<float>(CSSPropertyOutlineWidth, &RenderStyle::outlineWidth, &RenderStyle::setOutlineWidth), > new PropertyWrapper<float>(CSSPropertyLetterSpacing, &RenderStyle::letterSpacing, &RenderStyle::setLetterSpacing), >- new LengthPropertyWrapper<Length>(CSSPropertyWordSpacing, &RenderStyle::wordSpacing, &RenderStyle::setWordSpacing), >- new LengthPropertyWrapper<Length>(CSSPropertyTextIndent, &RenderStyle::textIndent, &RenderStyle::setTextIndent), >+ new LengthPropertyWrapper(CSSPropertyWordSpacing, &RenderStyle::wordSpacing, &RenderStyle::setWordSpacing), >+ new LengthPropertyWrapper(CSSPropertyTextIndent, &RenderStyle::textIndent, &RenderStyle::setTextIndent), > > new PropertyWrapper<float>(CSSPropertyPerspective, &RenderStyle::perspective, &RenderStyle::setPerspective), >- new LengthPropertyWrapper<Length>(CSSPropertyPerspectiveOriginX, &RenderStyle::perspectiveOriginX, &RenderStyle::setPerspectiveOriginX), >- new LengthPropertyWrapper<Length>(CSSPropertyPerspectiveOriginY, &RenderStyle::perspectiveOriginY, &RenderStyle::setPerspectiveOriginY), >- new LengthPropertyWrapper<Length>(CSSPropertyTransformOriginX, &RenderStyle::transformOriginX, &RenderStyle::setTransformOriginX), >- new LengthPropertyWrapper<Length>(CSSPropertyTransformOriginY, &RenderStyle::transformOriginY, &RenderStyle::setTransformOriginY), >+ new LengthPropertyWrapper(CSSPropertyPerspectiveOriginX, &RenderStyle::perspectiveOriginX, &RenderStyle::setPerspectiveOriginX), >+ new LengthPropertyWrapper(CSSPropertyPerspectiveOriginY, &RenderStyle::perspectiveOriginY, &RenderStyle::setPerspectiveOriginY), >+ new LengthPropertyWrapper(CSSPropertyTransformOriginX, &RenderStyle::transformOriginX, &RenderStyle::setTransformOriginX), >+ new LengthPropertyWrapper(CSSPropertyTransformOriginY, &RenderStyle::transformOriginY, &RenderStyle::setTransformOriginY), > new PropertyWrapper<float>(CSSPropertyTransformOriginZ, &RenderStyle::transformOriginZ, &RenderStyle::setTransformOriginZ), >- new LengthPropertyWrapper<LengthSize>(CSSPropertyBorderTopLeftRadius, &RenderStyle::borderTopLeftRadius, &RenderStyle::setBorderTopLeftRadius), >- new LengthPropertyWrapper<LengthSize>(CSSPropertyBorderTopRightRadius, &RenderStyle::borderTopRightRadius, &RenderStyle::setBorderTopRightRadius), >- new LengthPropertyWrapper<LengthSize>(CSSPropertyBorderBottomLeftRadius, &RenderStyle::borderBottomLeftRadius, &RenderStyle::setBorderBottomLeftRadius), >- new LengthPropertyWrapper<LengthSize>(CSSPropertyBorderBottomRightRadius, &RenderStyle::borderBottomRightRadius, &RenderStyle::setBorderBottomRightRadius), >+ new LengthVariantPropertyWrapper<LengthSize>(CSSPropertyBorderTopLeftRadius, &RenderStyle::borderTopLeftRadius, &RenderStyle::setBorderTopLeftRadius), >+ new LengthVariantPropertyWrapper<LengthSize>(CSSPropertyBorderTopRightRadius, &RenderStyle::borderTopRightRadius, &RenderStyle::setBorderTopRightRadius), >+ new LengthVariantPropertyWrapper<LengthSize>(CSSPropertyBorderBottomLeftRadius, &RenderStyle::borderBottomLeftRadius, &RenderStyle::setBorderBottomLeftRadius), >+ new LengthVariantPropertyWrapper<LengthSize>(CSSPropertyBorderBottomRightRadius, &RenderStyle::borderBottomRightRadius, &RenderStyle::setBorderBottomRightRadius), > new PropertyWrapper<Visibility>(CSSPropertyVisibility, &RenderStyle::visibility, &RenderStyle::setVisibility), > new PropertyWrapper<float>(CSSPropertyZoom, &RenderStyle::zoom, &RenderStyle::setZoomWithoutReturnValue), > >- new LengthPropertyWrapper<LengthBox>(CSSPropertyClip, &RenderStyle::clip, &RenderStyle::setClip), >+ new LengthVariantPropertyWrapper<LengthBox>(CSSPropertyClip, &RenderStyle::clip, &RenderStyle::setClip), > > new PropertyWrapperAcceleratedOpacity(), > new PropertyWrapperAcceleratedTransform(), >@@ -1569,7 +1593,7 @@ CSSPropertyAnimationWrapperMap::CSSPropertyAnimationWrapperMap() > new PropertyWrapperClipPath(CSSPropertyWebkitClipPath, &RenderStyle::clipPath, &RenderStyle::setClipPath), > > new PropertyWrapperShape(CSSPropertyShapeOutside, &RenderStyle::shapeOutside, &RenderStyle::setShapeOutside), >- new LengthPropertyWrapper<Length>(CSSPropertyShapeMargin, &RenderStyle::shapeMargin, &RenderStyle::setShapeMargin), >+ new LengthPropertyWrapper(CSSPropertyShapeMargin, &RenderStyle::shapeMargin, &RenderStyle::setShapeMargin), > new PropertyWrapper<float>(CSSPropertyShapeImageThreshold, &RenderStyle::shapeImageThreshold, &RenderStyle::setShapeImageThreshold), > > new PropertyWrapperVisitedAffectedColor(CSSPropertyColumnRuleColor, MaybeInvalidColor, &RenderStyle::columnRuleColor, &RenderStyle::setColumnRuleColor, &RenderStyle::visitedLinkColumnRuleColor, &RenderStyle::setVisitedLinkColumnRuleColor), >@@ -1593,15 +1617,15 @@ CSSPropertyAnimationWrapperMap::CSSPropertyAnimationWrapperMap() > new PropertyWrapper<Vector<SVGLengthValue>>(CSSPropertyStrokeDasharray, &RenderStyle::strokeDashArray, &RenderStyle::setStrokeDashArray), > new PropertyWrapper<float>(CSSPropertyStrokeMiterlimit, &RenderStyle::strokeMiterLimit, &RenderStyle::setStrokeMiterLimit), > >- new LengthPropertyWrapper<Length>(CSSPropertyCx, &RenderStyle::cx, &RenderStyle::setCx), >- new LengthPropertyWrapper<Length>(CSSPropertyCy, &RenderStyle::cy, &RenderStyle::setCy), >- new LengthPropertyWrapper<Length>(CSSPropertyR, &RenderStyle::r, &RenderStyle::setR), >- new LengthPropertyWrapper<Length>(CSSPropertyRx, &RenderStyle::rx, &RenderStyle::setRx), >- new LengthPropertyWrapper<Length>(CSSPropertyRy, &RenderStyle::ry, &RenderStyle::setRy), >- new LengthPropertyWrapper<Length>(CSSPropertyStrokeDashoffset, &RenderStyle::strokeDashOffset, &RenderStyle::setStrokeDashOffset), >- new LengthPropertyWrapper<Length>(CSSPropertyStrokeWidth, &RenderStyle::strokeWidth, &RenderStyle::setStrokeWidth), >- new LengthPropertyWrapper<Length>(CSSPropertyX, &RenderStyle::x, &RenderStyle::setX), >- new LengthPropertyWrapper<Length>(CSSPropertyY, &RenderStyle::y, &RenderStyle::setY), >+ new LengthPropertyWrapper(CSSPropertyCx, &RenderStyle::cx, &RenderStyle::setCx), >+ new LengthPropertyWrapper(CSSPropertyCy, &RenderStyle::cy, &RenderStyle::setCy), >+ new LengthPropertyWrapper(CSSPropertyR, &RenderStyle::r, &RenderStyle::setR), >+ new LengthPropertyWrapper(CSSPropertyRx, &RenderStyle::rx, &RenderStyle::setRx), >+ new LengthPropertyWrapper(CSSPropertyRy, &RenderStyle::ry, &RenderStyle::setRy), >+ new LengthPropertyWrapper(CSSPropertyStrokeDashoffset, &RenderStyle::strokeDashOffset, &RenderStyle::setStrokeDashOffset), >+ new LengthPropertyWrapper(CSSPropertyStrokeWidth, &RenderStyle::strokeWidth, &RenderStyle::setStrokeWidth), >+ new LengthPropertyWrapper(CSSPropertyX, &RenderStyle::x, &RenderStyle::setX), >+ new LengthPropertyWrapper(CSSPropertyY, &RenderStyle::y, &RenderStyle::setY), > > new PropertyWrapper<float>(CSSPropertyFloodOpacity, &RenderStyle::floodOpacity, &RenderStyle::setFloodOpacity), > new PropertyWrapperMaybeInvalidColor(CSSPropertyFloodColor, &RenderStyle::floodColor, &RenderStyle::setFloodColor), >@@ -1758,6 +1782,14 @@ bool CSSPropertyAnimation::propertiesEqual(CSSPropertyID prop, const RenderStyle > return true; > } > >+bool CSSPropertyAnimation::canPropertyBeInterpolated(CSSPropertyID prop, const RenderStyle* a, const RenderStyle* b) >+{ >+ AnimationPropertyWrapperBase* wrapper = CSSPropertyAnimationWrapperMap::singleton().wrapperForProperty(prop); >+ if (wrapper) >+ return wrapper->canInterpolate(a, b); >+ return false; >+} >+ > CSSPropertyID CSSPropertyAnimation::getPropertyAtIndex(int i, bool& isShorthand) > { > CSSPropertyAnimationWrapperMap& map = CSSPropertyAnimationWrapperMap::singleton(); >diff --git a/Source/WebCore/page/animation/CSSPropertyAnimation.h b/Source/WebCore/page/animation/CSSPropertyAnimation.h >index e9fc7ffa744248b5afc2601585304919565cf78c..d3bd9c4e92346e08700a877c190ecff7c991ed26 100644 >--- a/Source/WebCore/page/animation/CSSPropertyAnimation.h >+++ b/Source/WebCore/page/animation/CSSPropertyAnimation.h >@@ -41,6 +41,7 @@ public: > static bool isPropertyAnimatable(CSSPropertyID); > static bool animationOfPropertyIsAccelerated(CSSPropertyID); > static bool propertiesEqual(CSSPropertyID, const RenderStyle* a, const RenderStyle* b); >+ static bool canPropertyBeInterpolated(CSSPropertyID, const RenderStyle* a, const RenderStyle* b); > static CSSPropertyID getPropertyAtIndex(int, bool& isShorthand); > static int getNumProperties(); > >diff --git a/Source/WebCore/style/StyleTreeResolver.cpp b/Source/WebCore/style/StyleTreeResolver.cpp >index 49e4d45edfee546f52aff5e309ff594d0bc52de9..e54ce5210e1c335c92543046690aca10c2ef1f77 100644 >--- a/Source/WebCore/style/StyleTreeResolver.cpp >+++ b/Source/WebCore/style/StyleTreeResolver.cpp >@@ -292,11 +292,13 @@ ElementUpdate TreeResolver::createAnimatedElementUpdate(std::unique_ptr<RenderSt > // First, we need to make sure that any new CSS animation occuring on this element has a matching WebAnimation > // on the document timeline. Note that we get timeline() on the Document here because we need a timeline created > // in case no Web Animations have been created through the JS API. >- if ((oldStyle && oldStyle->hasTransitions()) || newStyle->hasTransitions()) >- m_document.timeline().updateCSSTransitionsForElement(element, *newStyle, oldStyle); >+ if (element.document().pageCacheState() == Document::NotInPageCache && !element.document().renderView()->printing()) { >+ if (oldStyle && (oldStyle->hasTransitions() || newStyle->hasTransitions())) >+ m_document.timeline().updateCSSTransitionsForElement(element, *oldStyle, *newStyle); > >- if ((oldStyle && oldStyle->hasAnimations()) || newStyle->hasAnimations()) >- m_document.timeline().updateCSSAnimationsForElement(element, *newStyle, oldStyle); >+ if ((oldStyle && oldStyle->hasAnimations()) || newStyle->hasAnimations()) >+ m_document.timeline().updateCSSAnimationsForElement(element, oldStyle, *newStyle); >+ } > } > > if (auto timeline = m_document.existingTimeline()) { >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index 608fbc5adf4ec460ffbe37e4071917d636d8148b..eab6752d0eee32b9590e66628efa1879149e3775 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,28 @@ >+2018-06-18 Antoine Quint <graouts@apple.com> >+ >+ [Web Animations] Implement "Starting of transitions" section from CSS Transitions >+ https://bugs.webkit.org/show_bug.cgi?id=186517 >+ <rdar://problem/41000798> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Implementing the CSS Transitions spec for starting transitions highlighted a couple of issues with existing tests. >+ >+ * TestExpectations: The test imported/mozilla/css-transitions/test_animation-ready.html now passes reliably. >+ * animations/transition-and-animation-3-expected.txt: >+ * animations/transition-and-animation-3.html: This test was mistakenly expecting a retargeted transition to pick >+ up from the underlying value (100px) rather than the interrupted transition's value (~0px). We update the test >+ to be more obvious about what it is testing and with the correct behavior per the spec. >+ * transitions/background-position-transitions-expected.txt: >+ * transitions/background-position-transitions.html: Shorthand properties are expected to yield a transitiong for >+ each shorthand property, so we update this test to check the background-position shorthand properties. >+ * transitions/resources/transition-test-helpers.js: We uncovered a crash, which is not new to this patch, that forces >+ us to work around using the background-position longhand properties. So we work around this by reading from the shorthand >+ background-position property and manually parsing the value. Fixing this crash is tracked by webkit.org/b/186766. >+ * transitions/transition-to-from-auto-expected.txt: >+ * transitions/transition-to-from-auto.html: Update the test to check that we only yield transitions when interpolating >+ between non-auto values, as mandated by the spec. >+ > 2018-06-18 Zan Dobersek <zdobersek@igalia.com> > > Unreviewed WPE gardening. Manage the current set of CSS3 Filters and >diff --git a/LayoutTests/imported/mozilla/ChangeLog b/LayoutTests/imported/mozilla/ChangeLog >index 00e46f6ec9f01f070af206414e6c1948c80a6a7b..d22df25f9c2b8a30e7dadd04be9c28a945b3b112 100644 >--- a/LayoutTests/imported/mozilla/ChangeLog >+++ b/LayoutTests/imported/mozilla/ChangeLog >@@ -1,3 +1,16 @@ >+2018-06-18 Antoine Quint <graouts@apple.com> >+ >+ [Web Animations] Implement "Starting of transitions" section from CSS Transitions >+ https://bugs.webkit.org/show_bug.cgi?id=186517 >+ <rdar://problem/41000798> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Mark some progressions in the Mozilla CSS Animations and CSS Transitions tests. >+ >+ * css-transitions/test_animation-cancel-expected.txt: >+ * css-transitions/test_animation-ready-expected.txt: >+ > 2018-06-15 Antoine Quint <graouts@apple.com> > > [Web Animations] CSS Animations should take precedence over CSS Transitions >diff --git a/LayoutTests/TestExpectations b/LayoutTests/TestExpectations >index b8284b5d7c4678fee4808b21ece4397f1384d320..10881f453ee17fd9d7a66662d1fe1ebb7a8346d4 100644 >--- a/LayoutTests/TestExpectations >+++ b/LayoutTests/TestExpectations >@@ -1932,7 +1932,6 @@ webkit.org/b/183821 imported/mozilla/css-transitions/test_animation-cancel.html > webkit.org/b/183826 imported/mozilla/css-animations/test_animation-pausing.html [ Pass Failure Timeout ] > webkit.org/b/183828 imported/mozilla/css-animations/test_animation-playstate.html [ Pass Failure Timeout ] > webkit.org/b/183830 imported/mozilla/css-animations/test_animation-ready.html [ Pass Failure Timeout ] >-webkit.org/b/183831 imported/mozilla/css-transitions/test_animation-ready.html [ Pass Failure Timeout ] > webkit.org/b/183834 imported/mozilla/css-animations/test_animation-starttime.html [ Pass Failure Timeout ] > webkit.org/b/183836 imported/mozilla/css-animations/test_animations-dynamic-changes.html [ Pass Failure Timeout ] > webkit.org/b/183837 imported/mozilla/css-transitions/test_document-get-animations.html [ Pass Failure Timeout ] >diff --git a/LayoutTests/animations/transition-and-animation-3-expected.txt b/LayoutTests/animations/transition-and-animation-3-expected.txt >index 32234bc98cfc2d36e6357bf7c5c4c6ac38f61c8c..12f06dc99127f46d3fe1423f73dc0ac68fc9010a 100644 >--- a/LayoutTests/animations/transition-and-animation-3-expected.txt >+++ b/LayoutTests/animations/transition-and-animation-3-expected.txt >@@ -1,4 +1,13 @@ >-Once animation has finished, box should be running left transition from 100px to 200px. >+Once animation has finished, box should be running left transition from 0px to 200px. > >-PASS - "left" property for "test" element at 0.2s saw something close to: 100 >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS animations.length is 1 >+PASS animations[0] instanceof CSSTransition is true >+PASS animations[0].effect.getKeyframes()[0].left is not "100px" >+PASS animations[0].effect.getKeyframes()[1].left is "200px" >+PASS successfullyParsed is true >+ >+TEST COMPLETE > >diff --git a/LayoutTests/animations/transition-and-animation-3.html b/LayoutTests/animations/transition-and-animation-3.html >index cf73d3557eb5fccbf61d7ba7ce9728fc1a75da16..6020d7c3292a03bccdb47b17216cbb57f04457a1 100644 >--- a/LayoutTests/animations/transition-and-animation-3.html >+++ b/LayoutTests/animations/transition-and-animation-3.html >@@ -11,58 +11,62 @@ > background-color: blue; > } > >- .box.animating { >- -webkit-animation: move 0.1s linear; >+ .box.transitioning { >+ transition: left 10s linear; > left: 100px; >- -webkit-transition: left 10s linear; >+ } >+ >+ .box.animating { >+ animation: move 0.1s linear; > } > >- /* When the animation is done, the box should be running a transition from 100px to 200px */ >- .box.animating.moved { >+ .box.retargeted { > left: 200px; > } > >- @-webkit-keyframes move { >- from { >- left: 500px; >- } >- to { >- left: 501px; >- } >+ @keyframes move { >+ from { left: 500px } >+ to { left: 501px } > } > >- #result { >- margin-top: 130px; >- } > </style> >- <script src="resources/animation-test-helpers.js" type="text/javascript" charset="utf-8"></script> >+ <script src="../resources/js-test-pre.js"></script> >+</head> >+<body> >+ <div id="test" class="box"></div> > <script type="text/javascript" charset="utf-8"> > >- const expectedValues = [ >- // [animation-name, time, element-id, property, expected-value, tolerance] >- [null, 0.2, "test", "left", 100, 10], >- ]; >+ description("Once animation has finished, box should be running left transition from 0px to 200px."); > >- function animationStarted() >- { >- document.getElementById('test').className = 'animating moved box'; >- } >+ window.jsTestIsAsync = true; > >- function setupTest() >- { >- document.getElementById('test').className = 'animating box'; >- runAnimationTest(expectedValues, animationStarted); >- } >- >- window.addEventListener('load', function() { >- window.setTimeout(setupTest, 0); >- }, false); >+ let animations; >+ const testElement = document.getElementById('test'); >+ >+ // Start the test by starting a transition from 0 to 100px. >+ window.setTimeout(() => testElement.classList.add("transitioning")); >+ >+ // Then, once the transition has started, start an animation. >+ testElement.addEventListener("transitionstart", event => { >+ setTimeout(() => testElement.classList.add("animating")); >+ }); >+ >+ // Then wait for the animation to start and change the underlying left value. >+ testElement.addEventListener("animationstart", event => { >+ testElement.classList.add("retargeted"); >+ }); >+ >+ // When the animation has ended, check that we're transitioning from ~0 > 200, and not 100 > 200. >+ testElement.addEventListener("animationend", event => { >+ animations = testElement.getAnimations(); >+ shouldBe("animations.length", "1"); >+ shouldBeTrue("animations[0] instanceof CSSTransition"); >+ shouldNotBeEqualToString("animations[0].effect.getKeyframes()[0].left", "100px"); >+ shouldBeEqualToString("animations[0].effect.getKeyframes()[1].left", "200px"); >+ finishJSTest(); >+ }); > > </script> >-</head> >-<body> >- <p>Once animation has finished, box should be running left transition from 100px to 200px.</p> >- <div id="test" class="box"></div> >- <div id="result"></div> >+ <script src="../resources/js-test-post.js"></script> > </body> > </html> >diff --git a/LayoutTests/imported/mozilla/css-transitions/test_animation-cancel-expected.txt b/LayoutTests/imported/mozilla/css-transitions/test_animation-cancel-expected.txt >index 167e08e17d04f4b0388f45fd941940d296107865..003935e1da4542b170a8cb58c8dbdb8ee676d891 100644 >--- a/LayoutTests/imported/mozilla/css-transitions/test_animation-cancel-expected.txt >+++ b/LayoutTests/imported/mozilla/css-transitions/test_animation-cancel-expected.txt >@@ -4,10 +4,10 @@ PASS After canceling a transition, it can still be re-used > PASS After cancelling a finished transition, it can still be re-used > PASS After cancelling a transition, updating transition properties doesn't make it live again > PASS Setting display:none on an element cancels its transitions >-PASS Setting display:none cancels transitions on a child element >+FAIL Setting display:none cancels transitions on a child element assert_equals: expected "idle" but got "running" > PASS Removing a property from transition-property cancels transitions on that property > PASS Setting zero combined duration >-FAIL Changing style to another interpolable value cancels the original transition assert_equals: expected "idle" but got "finished" >-FAIL An after-change style value can't be interpolated assert_equals: There should be no transitions expected 0 but got 1 >-FAIL Reversing a running transition cancels the original transition assert_equals: expected "idle" but got "running" >+PASS Changing style to another interpolable value cancels the original transition >+PASS An after-change style value can't be interpolated >+PASS Reversing a running transition cancels the original transition > >diff --git a/LayoutTests/imported/mozilla/css-transitions/test_animation-ready-expected.txt b/LayoutTests/imported/mozilla/css-transitions/test_animation-ready-expected.txt >index 1724f91cffcaf7969931e278a68cffd534cf3d01..fd3ad85f16d8fa6209ac27efe435fc8f24f5ca16 100644 >--- a/LayoutTests/imported/mozilla/css-transitions/test_animation-ready-expected.txt >+++ b/LayoutTests/imported/mozilla/css-transitions/test_animation-ready-expected.txt >@@ -1,5 +1,5 @@ > > PASS A new ready promise is created each time play() is called the animation property > PASS ready promise is rejected when a transition is cancelled by updating transition-property >-FAIL ready promise is rejected when a transition is cancelled by changing the transition property to something not interpolable assert_equals: Animation is idle after transition was cancelled expected "idle" but got "paused" >+PASS ready promise is rejected when a transition is cancelled by changing the transition property to something not interpolable > >diff --git a/LayoutTests/transitions/background-position-transitions-expected.txt b/LayoutTests/transitions/background-position-transitions-expected.txt >index ac9ba486a28abef3892a7b2e952c3290de399e3b..8e213e90555a8cd20fcf59e813bcc068f846cf57 100644 >--- a/LayoutTests/transitions/background-position-transitions-expected.txt >+++ b/LayoutTests/transitions/background-position-transitions-expected.txt >@@ -1,4 +1,7 @@ >-PASS - "background-position" property for "box1" element at 0.5s saw something close to: 45,60 >-PASS - "background-position" property for "box2" element at 0.5s saw something close to: 45,60 >-PASS - "background-position" property for "box3" element at 0.5s saw something close to: 10,0.5,100,80,0,0.5,20,0.5,100,100,0,0.5 >+PASS - "background-position-x" property for "box1" element at 0.5s saw something close to: 45px >+PASS - "background-position-y" property for "box1" element at 0.5s saw something close to: 60px >+PASS - "background-position-x" property for "box2" element at 0.5s saw something close to: 45px >+PASS - "background-position-y" property for "box2" element at 0.5s saw something close to: 60px >+PASS - "background-position-x" property for "box3" element at 0.5s saw something close to: calc((10px * 0.5) + ((100% - 80px) * 0.5)) >+PASS - "background-position-y" property for "box3" element at 0.5s saw something close to: calc((20px * 0.5) + ((100% - 100px) * 0.5)) > >diff --git a/LayoutTests/transitions/background-position-transitions.html b/LayoutTests/transitions/background-position-transitions.html >index 2bbd06a9ff5e9b107669292526e17a13470c3439..2563277fb02261cad40981fdf8fe83f83eb02b4a 100644 >--- a/LayoutTests/transitions/background-position-transitions.html >+++ b/LayoutTests/transitions/background-position-transitions.html >@@ -41,9 +41,12 @@ > <script> > const expectedValues = [ > // [time, element-id, property, expected-value, tolerance] >- [0.5, 'box1', 'background-position', [45, 60], 2], >- [0.5, 'box2', 'background-position', [45, 60], 2], >- [0.5, 'box3', 'background-position', [10,0.5,100,80,0,0.5,20,0.5,100,100,0,0.5], 2], // Numbers extracted from a calc() expression. >+ [0.5, 'box1', 'background-position-x', "45px"], >+ [0.5, 'box1', 'background-position-y', "60px"], >+ [0.5, 'box2', 'background-position-x', "45px"], >+ [0.5, 'box2', 'background-position-y', "60px"], >+ [0.5, 'box3', 'background-position-x', "calc((10px * 0.5) + ((100% - 80px) * 0.5))"], >+ [0.5, 'box3', 'background-position-y', "calc((20px * 0.5) + ((100% - 100px) * 0.5))"], > ]; > > function setupTest() >diff --git a/LayoutTests/transitions/resources/transition-test-helpers.js b/LayoutTests/transitions/resources/transition-test-helpers.js >index ed39e252854e1cac86ac76264c66aad7216589ec..ebda795294eed1eb652ef9a7706909b269388712 100644 >--- a/LayoutTests/transitions/resources/transition-test-helpers.js >+++ b/LayoutTests/transitions/resources/transition-test-helpers.js >@@ -213,6 +213,30 @@ function checkExpectedValue(expected, index) > break; > } > } >+ } else if (property == "background-position-x" || property == "background-position-y") { >+ computedValue = window.getComputedStyle(document.getElementById(elementId)).backgroundPosition; >+ >+ const leftCharIndex = computedValue.indexOf("left"); >+ const rightCharIndex = computedValue.indexOf("right"); >+ const topCharIndex = computedValue.indexOf("top"); >+ const bottomCharIndex = computedValue.indexOf("bottom"); >+ >+ let firstCharIndex, lastCharIndex; >+ if (property == "background-position-x") { >+ if (computedValue.startsWith("left")) >+ firstCharIndex = 4; >+ else if (computedValue.startsWith("right")) >+ firstCharIndex = 5; >+ lastCharIndex = Math.max(topCharIndex, bottomCharIndex); >+ } else { >+ if (topCharIndex > -1) >+ firstCharIndex = topCharIndex + 3; >+ else >+ firstCharIndex = bottomCharIndex + 6; >+ lastCharIndex = computedValue.length; >+ } >+ >+ pass = computedValue.substring(firstCharIndex, lastCharIndex).trim() == expectedValue; > } else if (property == "fill" || property == "stroke") { > computedValue = window.getComputedStyle(document.getElementById(elementId)).getPropertyCSSValue(property).rgbColor; > if (compareRGB([computedValue.red.cssText, computedValue.green.cssText, computedValue.blue.cssText], expectedValue, tolerance)) >diff --git a/LayoutTests/transitions/transition-to-from-auto-expected.txt b/LayoutTests/transitions/transition-to-from-auto-expected.txt >index 529dcfa679b9f7078aa762ab100ed1f7dc5bca29..2902d0152403b25775702e4e3577fd7c345a3ef1 100644 >--- a/LayoutTests/transitions/transition-to-from-auto-expected.txt >+++ b/LayoutTests/transitions/transition-to-from-auto-expected.txt >@@ -1,4 +1,3 @@ >-PASS - "left" property for "test1" element at 1s saw something close to: 0 >-PASS - "left" property for "test2" element at 1s saw something close to: 100 >+Total number of animations: 1 > PASS - "left" property for "test3" element at 1s saw something close to: 50 > >diff --git a/LayoutTests/transitions/transition-to-from-auto.html b/LayoutTests/transitions/transition-to-from-auto.html >index 96103233bf4a639fc6bc50c41d225eca019951c9..3eaaa167d5e431bc55434bbaac051277e5244d00 100644 >--- a/LayoutTests/transitions/transition-to-from-auto.html >+++ b/LayoutTests/transitions/transition-to-from-auto.html >@@ -41,14 +41,13 @@ > > const expectedValues = [ > // [time, element-id, property, expected-value, tolerance] >- [1, 'test1', 'left', '0', 2], >- [1, 'test2', 'left', '100', 2], > [1, 'test3', 'left', '50', 2], > ]; > > function setupTest() > { > document.body.classList.add('final'); >+ result += `Total number of animations: ${document.getAnimations().length} <br>`; > } > > runTransitionTest(expectedValues, setupTest, usePauseAPI);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Flags:
dino
:
review+
ews-watchlist
:
commit-queue-
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 186517
: 342939 |
342949