Changeset 287707 in webkit
- Timestamp:
- Jan 6, 2022 11:57:38 AM (6 months ago)
- Location:
- trunk
- Files:
-
- 17 edited
-
LayoutTests/imported/w3c/ChangeLog (modified) (1 diff)
-
LayoutTests/imported/w3c/web-platform-tests/css/css-animations/KeyframeEffect-getKeyframes.tentative-expected.txt (modified) (1 diff)
-
LayoutTests/imported/w3c/web-platform-tests/css/css-animations/KeyframeEffect-setKeyframes.tentative-expected.txt (modified) (1 diff)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/animation/CSSAnimation.cpp (modified) (1 diff)
-
Source/WebCore/animation/CSSAnimation.h (modified) (3 diffs)
-
Source/WebCore/animation/ElementAnimationRareData.h (modified) (2 diffs)
-
Source/WebCore/animation/KeyframeEffect.cpp (modified) (1 diff)
-
Source/WebCore/animation/KeyframeEffect.h (modified) (1 diff)
-
Source/WebCore/css/CSSStyleSheet.cpp (modified) (4 diffs)
-
Source/WebCore/css/CSSStyleSheet.h (modified) (2 diffs)
-
Source/WebCore/dom/Document.cpp (modified) (2 diffs)
-
Source/WebCore/dom/Document.h (modified) (1 diff)
-
Source/WebCore/dom/Element.cpp (modified) (1 diff)
-
Source/WebCore/dom/Element.h (modified) (1 diff)
-
Source/WebCore/style/Styleable.cpp (modified) (3 diffs)
-
Source/WebCore/style/Styleable.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/imported/w3c/ChangeLog
r287688 r287707 1 2022-01-06 Antoine Quint <graouts@webkit.org> 2 3 [Web Animations] inserting a rule within a @keyframes rule should update animations 4 https://bugs.webkit.org/show_bug.cgi?id=234895 5 6 Reviewed by Darin Adler. 7 8 Mark WPT progressions. 9 10 * web-platform-tests/css/css-animations/KeyframeEffect-getKeyframes.tentative-expected.txt: 11 * web-platform-tests/css/css-animations/KeyframeEffect-setKeyframes.tentative-expected.txt: 12 1 13 2022-01-06 Martin Robinson <mrobinson@webkit.org> 2 14 -
trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/KeyframeEffect-getKeyframes.tentative-expected.txt
r287524 r287707 24 24 PASS KeyframeEffect.getKeyframes() returns expected values for animations with a CSS variable which is overriden by the value in keyframe 25 25 FAIL KeyframeEffect.getKeyframes() returns expected values for animations with only custom property in a keyframe assert_equals: value for 'transform' on Keyframe #0 should match expected "translate(100px)" but got "matrix(1, 0, 0, 1, 100, 0)" 26 FAIL KeyframeEffect.getKeyframes() reflects changes to @keyframes rules assert_equals: value for 'left' on Keyframes reflects the updated @keyframes rule should match expected "200px" but got "100px" 26 PASS KeyframeEffect.getKeyframes() reflects changes to @keyframes rules 27 27 -
trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/KeyframeEffect-setKeyframes.tentative-expected.txt
r267650 r287707 2 2 PASS KeyframeEffect.setKeyframes() causes subsequent changes to @keyframes rules to be ignored 3 3 PASS KeyframeEffect.setKeyframes() causes subsequent changes to animation-timing-function to be ignored 4 FAIL KeyframeEffect.setKeyframes() should NOT cause subsequent changes to @keyframes rules to be ignored if it threw assert_equals: value for 'left' on Keyframes reflect the value set via style should match expected "300px" but got "100px" 4 PASS KeyframeEffect.setKeyframes() should NOT cause subsequent changes to @keyframes rules to be ignored if it threw 5 5 -
trunk/Source/WebCore/ChangeLog
r287704 r287707 1 2022-01-06 Antoine Quint <graouts@webkit.org> 2 3 [Web Animations] inserting a rule within a @keyframes rule should update animations 4 https://bugs.webkit.org/show_bug.cgi?id=234895 5 6 Reviewed by Darin Adler. 7 8 Using the CSSOM, it is possible to insert or delete rules within an @keyframes rule. 9 In fact, there are two WPT that check this behavior with the getKeyframes() and 10 setKeyframes() methods. 11 12 This would not have any effect until now because when we consider whether to invalidate 13 animations in Styleable::updateCSSAnimations(), we look at the previous and current 14 AnimationList and don't see any difference because we look, as far as keyframes are 15 concerned, at the @keyframes name but not at the keyframes content. 16 17 Now, when a rule is added or deleted from an @keyframes rule using the CSSOM, we notify 18 the Document using the new keyframesRuleDidChange() method, which in turn checks all 19 CSSAnimation objects applied to elements in that document using that @keyframes rule 20 and notifies them of the change by calling keyframesRuleDidChange(). 21 22 This clears the keyframes on the associated KeyframeEffect, invalidates the target 23 and sets a flag on the ElementAnimationRareData that this element is pending update 24 to its CSS Animations' keyframe such that during the next call 25 Styleable::updateCSSAnimations() we force the update even if the previous and current 26 AnimationList look identical. 27 28 During that next call to Styleable::updateCSSAnimations(), we will call into the new 29 CSSAnimation::updateKeyframesIfNeeded() which will re-compute the keyframes based on the 30 current set of rules within the @keyframes rule. 31 32 The final piece of work required is to track when setKeyframes() is called on the effect 33 that updates to the @keyframes rule should no longer apply since they keyframes were overriden 34 by the Web Animations API. This is done by setting an additional flag in 35 CSSAnimation::effectKeyframesWereSetUsingBindings(). 36 37 * animation/CSSAnimation.cpp: 38 (WebCore::CSSAnimation::effectKeyframesWereSetUsingBindings): 39 (WebCore::CSSAnimation::keyframesRuleDidChange): 40 (WebCore::CSSAnimation::updateKeyframesIfNeeded): 41 * animation/CSSAnimation.h: 42 * animation/ElementAnimationRareData.h: 43 (WebCore::ElementAnimationRareData::cssAnimationsDidUpdate): 44 (WebCore::ElementAnimationRareData::keyframesRuleDidChange): 45 (WebCore::ElementAnimationRareData::hasPendingKeyframesUpdate const): 46 * animation/KeyframeEffect.cpp: 47 (WebCore::KeyframeEffect::keyframesRuleDidChange): 48 * animation/KeyframeEffect.h: 49 * css/CSSStyleSheet.cpp: 50 (WebCore::CSSStyleSheet::didMutateRules): 51 (WebCore::CSSStyleSheet::RuleMutationScope::RuleMutationScope): 52 (WebCore::CSSStyleSheet::RuleMutationScope::~RuleMutationScope): 53 * css/CSSStyleSheet.h: 54 * dom/Document.cpp: 55 (WebCore::Document::keyframesRuleDidChange): 56 * dom/Document.h: 57 * dom/Element.cpp: 58 (WebCore::Element::cssAnimationsDidUpdate): 59 (WebCore::Element::keyframesRuleDidChange): 60 (WebCore::Element::hasPendingKeyframesUpdate const): 61 * dom/Element.h: 62 * style/Styleable.cpp: 63 (WebCore::Styleable::updateCSSAnimations const): 64 * style/Styleable.h: 65 (WebCore::Styleable::keyframesRuleDidChange const): 66 1 67 2022-01-06 Andres Gonzalez <andresg_22@apple.com> 2 68 -
trunk/Source/WebCore/animation/CSSAnimation.cpp
r284693 r287707 238 238 // matching @keyframes rules or the resolved value of the animation-timing-function property for the target element will not 239 239 // be reflected in that animation. 240 m_overriddenProperties.add(Property::Keyframes); 240 241 m_overriddenProperties.add(Property::TimingFunction); 241 242 } 242 243 244 void CSSAnimation::keyframesRuleDidChange() 245 { 246 if (m_overriddenProperties.contains(Property::Keyframes) || !is<KeyframeEffect>(effect())) 247 return; 248 249 auto owningElement = this->owningElement(); 250 if (!owningElement) 251 return; 252 253 downcast<KeyframeEffect>(*effect()).keyframesRuleDidChange(); 254 owningElement->keyframesRuleDidChange(); 255 } 256 257 void CSSAnimation::updateKeyframesIfNeeded(const RenderStyle* oldStyle, const RenderStyle& newStyle, const Style::ResolutionContext& resolutionContext) 258 { 259 if (m_overriddenProperties.contains(Property::Keyframes) || !is<KeyframeEffect>(effect())) 260 return; 261 262 auto& keyframeEffect = downcast<KeyframeEffect>(*effect()); 263 if (keyframeEffect.blendingKeyframes().isEmpty()) 264 keyframeEffect.computeDeclarativeAnimationBlendingKeyframes(oldStyle, newStyle, resolutionContext); 265 } 266 243 267 Ref<AnimationEventBase> CSSAnimation::createEvent(const AtomString& eventType, double elapsedTime, const String& pseudoId, std::optional<Seconds> timelineTime) 244 268 { -
trunk/Source/WebCore/animation/CSSAnimation.h
r284693 r287707 47 47 void effectTimingWasUpdatedUsingBindings(OptionalEffectTiming); 48 48 void effectKeyframesWereSetUsingBindings(); 49 void keyframesRuleDidChange(); 50 void updateKeyframesIfNeeded(const RenderStyle* oldStyle, const RenderStyle& newStyle, const Style::ResolutionContext&); 49 51 50 52 private: … … 60 62 ExceptionOr<void> bindingsReverse() final; 61 63 62 enum class Property : uint 8_t {64 enum class Property : uint16_t { 63 65 Name = 1 << 0, 64 66 Duration = 1 << 1, … … 68 70 PlayState = 1 << 5, 69 71 Delay = 1 << 6, 70 FillMode = 1 << 7 72 FillMode = 1 << 7, 73 Keyframes = 1 << 8 71 74 }; 72 75 -
trunk/Source/WebCore/animation/ElementAnimationRareData.h
r267571 r287707 55 55 const RenderStyle* lastStyleChangeEventStyle() const { return m_lastStyleChangeEventStyle.get(); } 56 56 void setLastStyleChangeEventStyle(std::unique_ptr<const RenderStyle>&& style) { m_lastStyleChangeEventStyle = WTFMove(style); } 57 void cssAnimationsDidUpdate() { m_hasPendingKeyframesUpdate = false; } 58 void keyframesRuleDidChange() { m_hasPendingKeyframesUpdate = true; } 59 bool hasPendingKeyframesUpdate() const { return m_hasPendingKeyframesUpdate; } 57 60 58 61 private: … … 65 68 PropertyToTransitionMap m_runningTransitionsByProperty; 66 69 PseudoId m_pseudoId; 70 bool m_hasPendingKeyframesUpdate { false }; 67 71 }; 68 72 -
trunk/Source/WebCore/animation/KeyframeEffect.cpp
r287549 r287707 785 785 } 786 786 787 void KeyframeEffect::keyframesRuleDidChange() 788 { 789 ASSERT(is<CSSAnimation>(animation())); 790 clearBlendingKeyframes(); 791 invalidate(); 792 } 793 787 794 ExceptionOr<void> KeyframeEffect::processKeyframes(JSGlobalObject& lexicalGlobalObject, Strong<JSObject>&& keyframesInput) 788 795 { -
trunk/Source/WebCore/animation/KeyframeEffect.h
r286544 r287707 169 169 170 170 void stopAcceleratingTransformRelatedProperties(UseAcceleratedAction); 171 172 void keyframesRuleDidChange(); 171 173 172 174 private: -
trunk/Source/WebCore/css/CSSStyleSheet.cpp
r283851 r287707 152 152 } 153 153 154 void CSSStyleSheet::didMutateRules(RuleMutationType mutationType, WhetherContentsWereClonedForMutation contentsWereClonedForMutation, StyleRuleKeyframes* insertedKeyframesRule )154 void CSSStyleSheet::didMutateRules(RuleMutationType mutationType, WhetherContentsWereClonedForMutation contentsWereClonedForMutation, StyleRuleKeyframes* insertedKeyframesRule, const String& modifiedKeyframesRuleName) 155 155 { 156 156 ASSERT(m_contents->isMutable()); … … 171 171 } 172 172 173 if (mutationType == RuleInsertion && !contentsWereClonedForMutation && !scope->activeStyleSheetsContains(this)) { 174 if (insertedKeyframesRule) { 175 if (auto* resolver = scope->resolverIfExists()) 176 resolver->addKeyframeStyle(*insertedKeyframesRule); 177 return; 178 } 179 scope->didChangeActiveStyleSheetCandidates(); 180 return; 181 } 182 183 if (mutationType == KeyframesRuleMutation) { 184 if (auto* ownerDocument = this->ownerDocument()) 185 ownerDocument->keyframesRuleDidChange(modifiedKeyframesRuleName); 186 } 187 173 188 scope->didChangeStyleSheetContents(); 174 189 … … 402 417 CSSStyleSheet::RuleMutationScope::RuleMutationScope(CSSRule* rule) 403 418 : m_styleSheet(rule ? rule->parentStyleSheet() : nullptr) 404 , m_mutationType( OtherMutation)419 , m_mutationType(is<CSSKeyframesRule>(rule) ? KeyframesRuleMutation : OtherMutation) 405 420 , m_contentsWereClonedForMutation(ContentsWereNotClonedForMutation) 406 421 , m_insertedKeyframesRule(nullptr) 422 , m_modifiedKeyframesRuleName(is<CSSKeyframesRule>(rule) ? downcast<CSSKeyframesRule>(*rule).name() : emptyString()) 407 423 { 408 424 if (m_styleSheet) … … 413 429 { 414 430 if (m_styleSheet) 415 m_styleSheet->didMutateRules(m_mutationType, m_contentsWereClonedForMutation, m_insertedKeyframesRule );416 } 417 418 } 431 m_styleSheet->didMutateRules(m_mutationType, m_contentsWereClonedForMutation, m_insertedKeyframesRule, m_modifiedKeyframesRuleName); 432 } 433 434 } -
trunk/Source/WebCore/css/CSSStyleSheet.h
r279847 r287707 96 96 void clearHadRulesMutation() { m_mutatedRules = false; } 97 97 98 enum RuleMutationType { OtherMutation, RuleInsertion };98 enum RuleMutationType { OtherMutation, RuleInsertion, KeyframesRuleMutation }; 99 99 enum WhetherContentsWereClonedForMutation { ContentsWereNotClonedForMutation = 0, ContentsWereClonedForMutation }; 100 100 … … 111 111 WhetherContentsWereClonedForMutation m_contentsWereClonedForMutation; 112 112 StyleRuleKeyframes* m_insertedKeyframesRule; 113 String m_modifiedKeyframesRuleName; 113 114 }; 114 115 115 116 WhetherContentsWereClonedForMutation willMutateRules(); 116 void didMutateRules(RuleMutationType, WhetherContentsWereClonedForMutation, StyleRuleKeyframes* insertedKeyframesRule );117 void didMutateRules(RuleMutationType, WhetherContentsWereClonedForMutation, StyleRuleKeyframes* insertedKeyframesRule, const String& modifiedKeyframesRuleName); 117 118 void didMutateRuleFromCSSStyleDeclaration(); 118 119 void didMutate(); -
trunk/Source/WebCore/dom/Document.cpp
r287327 r287707 34 34 #include "BeforeUnloadEvent.h" 35 35 #include "CDATASection.h" 36 #include "CSSAnimation.h" 36 37 #include "CSSFontSelector.h" 37 38 #include "CSSParser.h" … … 8570 8571 } 8571 8572 8573 void Document::keyframesRuleDidChange(const String& name) 8574 { 8575 for (auto* animation : WebAnimation::instances()) { 8576 if (!is<CSSAnimation>(animation) || !animation->isRelevant()) 8577 continue; 8578 8579 auto& cssAnimation = downcast<CSSAnimation>(*animation); 8580 if (cssAnimation.animationName() != name) 8581 continue; 8582 8583 auto owningElement = cssAnimation.owningElement(); 8584 if (!owningElement || !owningElement->element.isConnected() || &owningElement->element.document() != this) 8585 continue; 8586 8587 cssAnimation.keyframesRuleDidChange(); 8588 } 8589 } 8590 8572 8591 void Document::addTopLayerElement(Element& element) 8573 8592 { -
trunk/Source/WebCore/dom/Document.h
r287611 r287707 1542 1542 DocumentTimelinesController* timelinesController() const { return m_timelinesController.get(); } 1543 1543 WEBCORE_EXPORT DocumentTimelinesController& ensureTimelinesController(); 1544 void keyframesRuleDidChange(const String& name); 1544 1545 1545 1546 void addTopLayerElement(Element&); -
trunk/Source/WebCore/dom/Element.cpp
r287563 r287707 4051 4051 } 4052 4052 4053 void Element::cssAnimationsDidUpdate(PseudoId pseudoId) 4054 { 4055 ensureAnimationRareData(pseudoId).cssAnimationsDidUpdate(); 4056 } 4057 4058 void Element::keyframesRuleDidChange(PseudoId pseudoId) 4059 { 4060 ensureAnimationRareData(pseudoId).keyframesRuleDidChange(); 4061 } 4062 4063 bool Element::hasPendingKeyframesUpdate(PseudoId pseudoId) const 4064 { 4065 auto* data = animationRareData(pseudoId); 4066 return data && data->hasPendingKeyframesUpdate(); 4067 } 4068 4053 4069 void Element::disconnectFromResizeObservers() 4054 4070 { -
trunk/Source/WebCore/dom/Element.h
r287563 r287707 533 533 void setLastStyleChangeEventStyle(PseudoId, std::unique_ptr<const RenderStyle>&&); 534 534 535 void cssAnimationsDidUpdate(PseudoId); 536 void keyframesRuleDidChange(PseudoId); 537 bool hasPendingKeyframesUpdate(PseudoId) const; 538 535 539 bool isInTopLayer() const { return hasNodeFlag(NodeFlag::IsInTopLayer); } 536 540 void addToTopLayer(); -
trunk/Source/WebCore/style/Styleable.cpp
r287548 r287707 231 231 auto* currentAnimationList = newStyle.animations(); 232 232 auto* previousAnimationList = keyframeEffectStack.cssAnimationList(); 233 if ( previousAnimationList && !previousAnimationList->isEmpty() && newStyle.hasAnimations() && *(previousAnimationList) == *(newStyle.animations()))233 if (!element.hasPendingKeyframesUpdate(pseudoId) && previousAnimationList && !previousAnimationList->isEmpty() && newStyle.hasAnimations() && *(previousAnimationList) == *(newStyle.animations())) 234 234 return; 235 235 … … 258 258 // the Animation found in the current style. 259 259 previousAnimation->setBackingAnimation(currentAnimation); 260 // Keyframes may have been cleared if the @keyframes rules was changed since 261 // the last style update, so we must ensure keyframes are picked up. 262 previousAnimation->updateKeyframesIfNeeded(currentStyle, newStyle, resolutionContext); 260 263 newAnimations.add(previousAnimation); 261 264 // Remove the matched animation from the list of previous animations so we may not match it again. … … 282 285 283 286 keyframeEffectStack.setCSSAnimationList(currentAnimationList); 287 288 element.cssAnimationsDidUpdate(pseudoId); 284 289 } 285 290 -
trunk/Source/WebCore/style/Styleable.h
r284693 r287707 146 146 } 147 147 148 void keyframesRuleDidChange() const 149 { 150 element.keyframesRuleDidChange(pseudoId); 151 } 152 148 153 void elementWasRemoved() const; 149 154
Note: See TracChangeset
for help on using the changeset viewer.