Diff
Modified: trunk/Source/WebCore/ChangeLog (260075 => 260076)
--- trunk/Source/WebCore/ChangeLog 2020-04-14 16:16:11 UTC (rev 260075)
+++ trunk/Source/WebCore/ChangeLog 2020-04-14 16:19:47 UTC (rev 260076)
@@ -1,3 +1,54 @@
+2020-04-14 Antoine Quint <grao...@apple.com>
+
+ [Web Animations] Store an Element / PseudoId pair to define the KeyframeEffect target
+ https://bugs.webkit.org/show_bug.cgi?id=210491
+
+ Reviewed by Antti Koivisto.
+
+ In preparation for webkit.org/b/207290 where we will expose the `pseudoElement` JS API on KeyframeEffect we now
+ use an Element / PseudoId (m_target / m_pseudoId) pair to specify an effect's target. In the cases where it matters,
+ such as accessing the various animation collections exposed through Element and the KeyframeEffectStack, we now use
+ the new KeyframeEffect::targetElementOrPseudoElement() method to access the Element or PseudoElement targeted with
+ the Element / PseudoId pair.
+
+ * animation/AnimationTimeline.cpp:
+ (WebCore::AnimationTimeline::removeAnimation):
+ * animation/DeclarativeAnimation.cpp:
+ (WebCore::DeclarativeAnimation::initialize):
+ * animation/DocumentTimeline.cpp:
+ (WebCore::DocumentTimeline::transitionDidComplete):
+ (WebCore::DocumentTimeline::animationAcceleratedRunningStateDidChange):
+ * animation/KeyframeEffect.cpp:
+ (WebCore::KeyframeEffect::create):
+ (WebCore::KeyframeEffect::KeyframeEffect):
+ (WebCore::KeyframeEffect::copyPropertiesFromSource):
+ (WebCore::KeyframeEffect::getKeyframes):
+ (WebCore::KeyframeEffect::forceLayoutIfNeeded):
+ (WebCore::KeyframeEffect::computeCSSAnimationBlendingKeyframes):
+ (WebCore::KeyframeEffect::computeCSSTransitionBlendingKeyframes):
+ (WebCore::KeyframeEffect::animationTimelineDidChange):
+ (WebCore::KeyframeEffect::updateEffectStackMembership):
+ (WebCore::KeyframeEffect::targetElementOrPseudoElement const):
+ (WebCore::KeyframeEffect::setTarget):
+ (WebCore::KeyframeEffect::apply):
+ (WebCore::KeyframeEffect::invalidate):
+ (WebCore::KeyframeEffect::getAnimatedStyle):
+ (WebCore::KeyframeEffect::applyPendingAcceleratedActions):
+ (WebCore::KeyframeEffect::document const):
+ (WebCore::KeyframeEffect::renderer const):
+ * animation/KeyframeEffect.h:
+ * animation/KeyframeEffectStack.cpp:
+ (WebCore::KeyframeEffectStack::addEffect):
+ * animation/WebAnimation.cpp:
+ (WebCore::WebAnimation::setEffectInternal):
+ (WebCore::WebAnimation::setTimeline):
+ (WebCore::WebAnimation::persist):
+ * dom/Document.cpp:
+ (WebCore::Document::matchingAnimations):
+ * inspector/agents/InspectorAnimationAgent.cpp:
+ (WebCore::buildObjectForKeyframes):
+ (WebCore::InspectorAnimationAgent::requestEffectTarget):
+
2020-04-14 Simon Fraser <simon.fra...@apple.com>
[Async overflow scroll] Custom scrollbars on gmail don't show
Modified: trunk/Source/WebCore/animation/AnimationTimeline.cpp (260075 => 260076)
--- trunk/Source/WebCore/animation/AnimationTimeline.cpp 2020-04-14 16:16:11 UTC (rev 260075)
+++ trunk/Source/WebCore/animation/AnimationTimeline.cpp 2020-04-14 16:19:47 UTC (rev 260076)
@@ -84,7 +84,7 @@
ASSERT(!animation.timeline() || animation.timeline() == this);
m_animations.remove(&animation);
if (is<KeyframeEffect>(animation.effect())) {
- if (auto* target = downcast<KeyframeEffect>(animation.effect())->target()) {
+ if (auto* target = downcast<KeyframeEffect>(animation.effect())->targetElementOrPseudoElement()) {
animationWasRemovedFromElement(animation, *target);
target->ensureKeyframeEffectStack().removeEffect(*downcast<KeyframeEffect>(animation.effect()));
}
Modified: trunk/Source/WebCore/animation/DeclarativeAnimation.cpp (260075 => 260076)
--- trunk/Source/WebCore/animation/DeclarativeAnimation.cpp 2020-04-14 16:16:11 UTC (rev 260075)
+++ trunk/Source/WebCore/animation/DeclarativeAnimation.cpp 2020-04-14 16:19:47 UTC (rev 260076)
@@ -108,7 +108,12 @@
ASSERT(m_owningElement);
- setEffect(KeyframeEffect::create(*m_owningElement));
+ if (is<PseudoElement>(m_owningElement.get())) {
+ auto& pseudoOwningElement = downcast<PseudoElement>(*m_owningElement);
+ ASSERT(pseudoOwningElement.hostElement());
+ setEffect(KeyframeEffect::create(*pseudoOwningElement.hostElement(), pseudoOwningElement.pseudoId()));
+ } else
+ setEffect(KeyframeEffect::create(*m_owningElement, m_owningElement->pseudoId()));
setTimeline(&m_owningElement->document().timeline());
downcast<KeyframeEffect>(effect())->computeDeclarativeAnimationBlendingKeyframes(oldStyle, newStyle);
syncPropertiesWithBackingAnimation();
Modified: trunk/Source/WebCore/animation/DocumentTimeline.cpp (260075 => 260076)
--- trunk/Source/WebCore/animation/DocumentTimeline.cpp 2020-04-14 16:16:11 UTC (rev 260075)
+++ trunk/Source/WebCore/animation/DocumentTimeline.cpp 2020-04-14 16:19:47 UTC (rev 260076)
@@ -545,7 +545,7 @@
ASSERT(transition);
removeAnimation(*transition);
if (is<KeyframeEffect>(transition->effect())) {
- if (auto* target = downcast<KeyframeEffect>(transition->effect())->target())
+ if (auto* target = downcast<KeyframeEffect>(transition->effect())->targetElementOrPseudoElement())
target->ensureCompletedTransitionsByProperty().set(transition->property(), transition);
}
}
@@ -669,7 +669,7 @@
m_acceleratedAnimationsPendingRunningStateChange.add(&animation);
if (is<KeyframeEffect>(animation.effect())) {
- if (auto* target = downcast<KeyframeEffect>(animation.effect())->target())
+ if (auto* target = downcast<KeyframeEffect>(animation.effect())->targetElementOrPseudoElement())
updateListOfElementsWithRunningAcceleratedAnimationsForElement(*target);
}
Modified: trunk/Source/WebCore/animation/KeyframeEffect.cpp (260075 => 260076)
--- trunk/Source/WebCore/animation/KeyframeEffect.cpp 2020-04-14 16:16:11 UTC (rev 260075)
+++ trunk/Source/WebCore/animation/KeyframeEffect.cpp 2020-04-14 16:19:47 UTC (rev 260076)
@@ -46,6 +46,7 @@
#include "JSKeyframeEffect.h"
#include "KeyframeEffectStack.h"
#include "Logging.h"
+#include "PseudoElement.h"
#include "RenderBox.h"
#include "RenderBoxModelObject.h"
#include "RenderElement.h"
@@ -475,7 +476,7 @@
ExceptionOr<Ref<KeyframeEffect>> KeyframeEffect::create(JSGlobalObject& lexicalGlobalObject, Element* target, Strong<JSObject>&& keyframes, Optional<Variant<double, KeyframeEffectOptions>>&& options)
{
- auto keyframeEffect = adoptRef(*new KeyframeEffect(target));
+ auto keyframeEffect = adoptRef(*new KeyframeEffect(target, PseudoId::None));
if (options) {
OptionalEffectTiming timing;
@@ -510,18 +511,19 @@
ExceptionOr<Ref<KeyframeEffect>> KeyframeEffect::create(JSC::JSGlobalObject&, Ref<KeyframeEffect>&& source)
{
- auto keyframeEffect = adoptRef(*new KeyframeEffect(nullptr));
+ auto keyframeEffect = adoptRef(*new KeyframeEffect(nullptr, PseudoId::None));
keyframeEffect->copyPropertiesFromSource(WTFMove(source));
return keyframeEffect;
}
-Ref<KeyframeEffect> KeyframeEffect::create(const Element& target)
+Ref<KeyframeEffect> KeyframeEffect::create(const Element& target, PseudoId pseudoId)
{
- return adoptRef(*new KeyframeEffect(const_cast<Element*>(&target)));
+ return adoptRef(*new KeyframeEffect(const_cast<Element*>(&target), pseudoId));
}
-KeyframeEffect::KeyframeEffect(Element* target)
+KeyframeEffect::KeyframeEffect(Element* target, PseudoId pseudoId)
: m_target(makeWeakPtr(target))
+ , m_pseudoId(pseudoId)
{
}
@@ -528,6 +530,7 @@
void KeyframeEffect::copyPropertiesFromSource(Ref<KeyframeEffect>&& source)
{
m_target = source->m_target;
+ m_pseudoId = source->m_pseudoId;
m_compositeOperation = source->m_compositeOperation;
m_iterationCompositeOperation = source->m_iterationCompositeOperation;
@@ -581,10 +584,10 @@
// 3. For each keyframe in keyframes perform the following steps:
if (is<DeclarativeAnimation>(animation())) {
- auto* target = this->target();
+ auto* target = m_target.get();
auto* renderer = this->renderer();
- auto computedStyleExtractor = ComputedStyleExtractor(target);
+ auto computedStyleExtractor = ComputedStyleExtractor(target, false, m_pseudoId);
for (size_t i = 0; i < m_blendingKeyframes.size(); ++i) {
// 1. Initialize a dictionary object, output keyframe, using the following definition:
@@ -793,11 +796,12 @@
if (!m_needsForcedLayout || !m_target)
return false;
- auto* renderer = m_target->renderer();
+ auto* renderer = this->renderer();
if (!renderer || !renderer->parent())
return false;
- auto* frameView = m_target->document().view();
+ ASSERT(document());
+ auto* frameView = document()->view();
if (!frameView)
return false;
@@ -936,6 +940,7 @@
void KeyframeEffect::computeCSSAnimationBlendingKeyframes(const RenderStyle& unanimatedStyle)
{
ASSERT(is<CSSAnimation>(animation()));
+ ASSERT(document());
auto cssAnimation = downcast<CSSAnimation>(animation());
auto& backingAnimation = cssAnimation->backingAnimation();
@@ -947,7 +952,7 @@
// Ensure resource loads for all the frames.
for (auto& keyframe : keyframeList.keyframes()) {
if (auto* style = const_cast<RenderStyle*>(keyframe.style()))
- Style::loadPendingResources(*style, m_target->document(), m_target.get());
+ Style::loadPendingResources(*style, *document(), m_target.get());
}
m_blendingKeyframesSource = BlendingKeyframesSource::CSSAnimation;
@@ -957,6 +962,7 @@
void KeyframeEffect::computeCSSTransitionBlendingKeyframes(const RenderStyle* oldStyle, const RenderStyle& newStyle)
{
ASSERT(is<CSSTransition>(animation()));
+ ASSERT(document());
if (!oldStyle || m_blendingKeyframes.size())
return;
@@ -965,7 +971,7 @@
auto toStyle = RenderStyle::clonePtr(newStyle);
if (m_target)
- Style::loadPendingResources(*toStyle, m_target->document(), m_target.get());
+ Style::loadPendingResources(*toStyle, *document(), m_target.get());
KeyframeList keyframeList("keyframe-effect-" + createCanonicalUUIDString());
keyframeList.addProperty(property);
@@ -1023,13 +1029,13 @@
void KeyframeEffect::animationTimelineDidChange(AnimationTimeline* timeline)
{
- if (!m_target)
+ if (!targetElementOrPseudoElement())
return;
if (timeline)
- m_inTargetEffectStack = m_target->ensureKeyframeEffectStack().addEffect(*this);
+ m_inTargetEffectStack = targetElementOrPseudoElement()->ensureKeyframeEffectStack().addEffect(*this);
else {
- m_target->ensureKeyframeEffectStack().removeEffect(*this);
+ targetElementOrPseudoElement()->ensureKeyframeEffectStack().removeEffect(*this);
m_inTargetEffectStack = false;
}
}
@@ -1041,14 +1047,14 @@
void KeyframeEffect::updateEffectStackMembership()
{
- if (!m_target)
+ if (!targetElementOrPseudoElement())
return;
bool isRelevant = animation() && animation()->isRelevant();
if (isRelevant && !m_inTargetEffectStack)
- m_inTargetEffectStack = m_target->ensureKeyframeEffectStack().addEffect(*this);
+ m_inTargetEffectStack = targetElementOrPseudoElement()->ensureKeyframeEffectStack().addEffect(*this);
else if (!isRelevant && m_inTargetEffectStack) {
- m_target->ensureKeyframeEffectStack().removeEffect(*this);
+ targetElementOrPseudoElement()->ensureKeyframeEffectStack().removeEffect(*this);
m_inTargetEffectStack = false;
}
}
@@ -1066,15 +1072,38 @@
updateEffectStackMembership();
}
+Element* KeyframeEffect::targetElementOrPseudoElement() const
+{
+ if (m_pseudoId == PseudoId::None)
+ return m_target.get();
+
+ ASSERT(m_target.get());
+
+ if (m_pseudoId == PseudoId::Before)
+ return m_target->beforePseudoElement();
+
+ if (m_pseudoId == PseudoId::After)
+ return m_target->afterPseudoElement();
+
+ // We only support targeting ::before and ::after pseudo-elements at the moment.
+ ASSERT_NOT_REACHED();
+ return nullptr;
+}
+
void KeyframeEffect::setTarget(RefPtr<Element>&& newTarget)
{
- if (m_target.get() == newTarget.get())
+ auto* previousTarget = targetElementOrPseudoElement();
+ if (previousTarget == newTarget.get())
return;
- auto previousTarget = std::exchange(m_target, makeWeakPtr(newTarget.get()));
+ m_target = makeWeakPtr(newTarget.get());
+ // Until we support pseudo-elements via the Web Animations API, changing target means we should reset m_pseudoId.
+ // https://bugs.webkit.org/show_bug.cgi?id=207290
+ m_pseudoId = PseudoId::None;
+
if (auto* effectAnimation = animation())
- effectAnimation->effectTargetDidChange(previousTarget.get(), m_target.get());
+ effectAnimation->effectTargetDidChange(previousTarget, targetElementOrPseudoElement());
clearBlendingKeyframes();
@@ -1084,14 +1113,14 @@
// Likewise, we need to invalidate styles on the previous target so that
// any animated styles are removed immediately.
- invalidateElement(previousTarget.get());
+ invalidateElement(previousTarget);
if (previousTarget) {
previousTarget->ensureKeyframeEffectStack().removeEffect(*this);
m_inTargetEffectStack = false;
}
- if (m_target)
- m_inTargetEffectStack = m_target->ensureKeyframeEffectStack().addEffect(*this);
+ if (targetElementOrPseudoElement())
+ m_inTargetEffectStack = targetElementOrPseudoElement()->ensureKeyframeEffectStack().addEffect(*this);
}
void KeyframeEffect::apply(RenderStyle& targetStyle)
@@ -1104,7 +1133,7 @@
auto computedTiming = getComputedTiming();
m_phaseAtLastApplication = computedTiming.phase;
- InspectorInstrumentation::willApplyKeyframeEffect(*m_target, *this, computedTiming);
+ InspectorInstrumentation::willApplyKeyframeEffect(*targetElementOrPseudoElement(), *this, computedTiming);
if (!computedTiming.progress)
return;
@@ -1133,7 +1162,7 @@
void KeyframeEffect::invalidate()
{
- invalidateElement(m_target.get());
+ invalidateElement(targetElementOrPseudoElement());
}
void KeyframeEffect::computeAcceleratedPropertiesState()
@@ -1161,7 +1190,7 @@
void KeyframeEffect::getAnimatedStyle(std::unique_ptr<RenderStyle>& animatedStyle)
{
- if (!m_target || !renderer() || !animation())
+ if (!renderer() || !animation())
return;
auto progress = getComputedTiming().progress;
@@ -1483,8 +1512,9 @@
renderer->animationSeeked(timeOffset, m_blendingKeyframes.animationName());
break;
case AcceleratedAction::Stop:
+ ASSERT(document());
renderer->animationFinished(m_blendingKeyframes.animationName());
- if (!m_target->document().renderTreeBeingDestroyed())
+ if (!document()->renderTreeBeingDestroyed())
m_target->invalidateStyleAndLayerComposition();
m_isRunningAccelerated = false;
break;
@@ -1540,9 +1570,14 @@
return animation;
}
+Document* KeyframeEffect::document() const
+{
+ return m_target ? &m_target->document() : nullptr;
+}
+
RenderElement* KeyframeEffect::renderer() const
{
- return m_target ? m_target->renderer() : nullptr;
+ return targetElementOrPseudoElement() ? targetElementOrPseudoElement()->renderer() : nullptr;
}
const RenderStyle& KeyframeEffect::currentStyle() const
Modified: trunk/Source/WebCore/animation/KeyframeEffect.h (260075 => 260076)
--- trunk/Source/WebCore/animation/KeyframeEffect.h 2020-04-14 16:16:11 UTC (rev 260075)
+++ trunk/Source/WebCore/animation/KeyframeEffect.h 2020-04-14 16:19:47 UTC (rev 260076)
@@ -50,7 +50,7 @@
public:
static ExceptionOr<Ref<KeyframeEffect>> create(JSC::JSGlobalObject&, Element*, JSC::Strong<JSC::JSObject>&&, Optional<Variant<double, KeyframeEffectOptions>>&&);
static ExceptionOr<Ref<KeyframeEffect>> create(JSC::JSGlobalObject&, Ref<KeyframeEffect>&&);
- static Ref<KeyframeEffect> create(const Element&);
+ static Ref<KeyframeEffect> create(const Element&, PseudoId);
~KeyframeEffect() { }
bool isKeyframeEffect() const final { return true; }
@@ -102,6 +102,7 @@
const Vector<ParsedKeyframe>& parsedKeyframes() const { return m_parsedKeyframes; }
Element* target() const { return m_target.get(); }
+ Element* targetElementOrPseudoElement() const;
void setTarget(RefPtr<Element>&&);
Vector<JSC::Strong<JSC::JSObject>> getKeyframes(JSC::JSGlobalObject&);
@@ -158,12 +159,13 @@
const RenderStyle* unanimatedStyle() const { return m_unanimatedStyle.get(); }
private:
- KeyframeEffect(Element*);
+ KeyframeEffect(Element*, PseudoId);
enum class AcceleratedAction : uint8_t { Play, Pause, Seek, Stop };
enum class BlendingKeyframesSource : uint8_t { CSSAnimation, CSSTransition, WebAnimation };
enum class AcceleratedProperties : uint8_t { None, Some, All };
+ Document* document() const;
void updateEffectStackMembership();
void copyPropertiesFromSource(Ref<KeyframeEffect>&&);
ExceptionOr<void> processKeyframes(JSC::JSGlobalObject&, JSC::Strong<JSC::JSObject>&&);
@@ -192,7 +194,7 @@
Vector<ParsedKeyframe> m_parsedKeyframes;
Vector<AcceleratedAction> m_pendingAcceleratedActions;
WeakPtr<Element> m_target;
-
+ PseudoId m_pseudoId { PseudoId::None };
std::unique_ptr<const RenderStyle> m_unanimatedStyle;
AcceleratedAction m_lastRecordedAcceleratedAction { AcceleratedAction::Stop };
Modified: trunk/Source/WebCore/animation/KeyframeEffectStack.cpp (260075 => 260076)
--- trunk/Source/WebCore/animation/KeyframeEffectStack.cpp 2020-04-14 16:16:11 UTC (rev 260075)
+++ trunk/Source/WebCore/animation/KeyframeEffectStack.cpp 2020-04-14 16:19:47 UTC (rev 260076)
@@ -46,7 +46,7 @@
{
// To qualify for membership in an effect stack, an effect must have a target, an animation, a timeline and be relevant.
// This method will be called in WebAnimation and KeyframeEffect as those properties change.
- if (!effect.target() || !effect.animation() || !effect.animation()->timeline() || !effect.animation()->isRelevant())
+ if (!effect.targetElementOrPseudoElement() || !effect.animation() || !effect.animation()->timeline() || !effect.animation()->isRelevant())
return false;
m_effects.append(makeWeakPtr(&effect));
Modified: trunk/Source/WebCore/animation/WebAnimation.cpp (260075 => 260076)
--- trunk/Source/WebCore/animation/WebAnimation.cpp 2020-04-14 16:16:11 UTC (rev 260075)
+++ trunk/Source/WebCore/animation/WebAnimation.cpp 2020-04-14 16:19:47 UTC (rev 260076)
@@ -197,11 +197,11 @@
Element* previousTarget = nullptr;
if (is<KeyframeEffect>(oldEffect))
- previousTarget = downcast<KeyframeEffect>(oldEffect.get())->target();
+ previousTarget = downcast<KeyframeEffect>(oldEffect.get())->targetElementOrPseudoElement();
Element* newTarget = nullptr;
if (is<KeyframeEffect>(m_effect))
- newTarget = downcast<KeyframeEffect>(m_effect.get())->target();
+ newTarget = downcast<KeyframeEffect>(m_effect.get())->targetElementOrPseudoElement();
// Update the effect-to-animation relationships and the timeline's animation map.
if (oldEffect) {
@@ -235,7 +235,7 @@
if (is<KeyframeEffect>(m_effect)) {
auto* keyframeEffect = downcast<KeyframeEffect>(m_effect.get());
- auto* target = keyframeEffect->target();
+ auto* target = keyframeEffect->targetElementOrPseudoElement();
if (target) {
// In the case of a declarative animation, we don't want to remove the animation from the relevant maps because
// while the timeline was set via the API, the element still has a transition or animation set up and we must
@@ -1348,7 +1348,7 @@
if (previousReplaceState == ReplaceState::Removed && m_timeline) {
if (is<KeyframeEffect>(m_effect)) {
auto& keyframeEffect = downcast<KeyframeEffect>(*m_effect);
- auto& target = *keyframeEffect.target();
+ auto& target = *keyframeEffect.targetElementOrPseudoElement();
m_timeline->animationWasAddedToElement(*this, target);
target.ensureKeyframeEffectStack().addEffect(keyframeEffect);
}
Modified: trunk/Source/WebCore/dom/Document.cpp (260075 => 260076)
--- trunk/Source/WebCore/dom/Document.cpp 2020-04-14 16:16:11 UTC (rev 260075)
+++ trunk/Source/WebCore/dom/Document.cpp 2020-04-14 16:19:47 UTC (rev 260076)
@@ -8129,7 +8129,7 @@
for (auto& animation : m_timeline->getAnimations()) {
auto* effect = animation->effect();
ASSERT(is<KeyframeEffect>(animation->effect()));
- auto* target = downcast<KeyframeEffect>(*effect).target();
+ auto* target = downcast<KeyframeEffect>(*effect).targetElementOrPseudoElement();
ASSERT(target);
if (function(*target))
animations.append(animation);
Modified: trunk/Source/WebCore/inspector/agents/InspectorAnimationAgent.cpp (260075 => 260076)
--- trunk/Source/WebCore/inspector/agents/InspectorAnimationAgent.cpp 2020-04-14 16:16:11 UTC (rev 260075)
+++ trunk/Source/WebCore/inspector/agents/InspectorAnimationAgent.cpp 2020-04-14 16:19:47 UTC (rev 260076)
@@ -122,7 +122,7 @@
auto* renderer = keyframeEffect.renderer();
// Synthesize CSS style declarations for each keyframe so the frontend can display them.
- ComputedStyleExtractor computedStyleExtractor(target);
+ ComputedStyleExtractor computedStyleExtractor(target, false, target->pseudoId());
for (size_t i = 0; i < blendingKeyframes.size(); ++i) {
auto& blendingKeyframe = blendingKeyframes[i];
@@ -299,7 +299,7 @@
auto& keyframeEffect = downcast<KeyframeEffect>(*effect);
- auto* target = keyframeEffect.target();
+ auto* target = keyframeEffect.targetElementOrPseudoElement();
if (!target) {
errorString = "Animation for given animationId does not have a target"_s;
return;