Diff
Modified: trunk/LayoutTests/imported/w3c/ChangeLog (269812 => 269813)
--- trunk/LayoutTests/imported/w3c/ChangeLog 2020-11-14 08:52:49 UTC (rev 269812)
+++ trunk/LayoutTests/imported/w3c/ChangeLog 2020-11-14 09:01:04 UTC (rev 269813)
@@ -1,5 +1,22 @@
2020-11-13 Antoine Quint <[email protected]>
+ Support animations on more pseudo-elements
+ https://bugs.webkit.org/show_bug.cgi?id=218792
+ <rdar://problem/71274485>
+
+ Reviewed by Antti Koivisto.
+
+ Add PASS results for WPT tests running animations on ::marker pseudo-elements.
+
+ * web-platform-tests/css/css-animations/Document-getAnimations.tentative-expected.txt:
+ * web-platform-tests/css/css-animations/animationevent-marker-pseudoelement-expected.txt:
+ * web-platform-tests/css/css-animations/event-order.tentative-expected.txt:
+ * web-platform-tests/css/css-pseudo/marker-animate-expected.txt:
+ * web-platform-tests/css/css-pseudo/parsing/marker-supported-properties-in-animation-expected.txt:
+ * web-platform-tests/css/css-transitions/Document-getAnimations.tentative-expected.txt:
+
+2020-11-13 Antoine Quint <[email protected]>
+
Add support for discrete animations of many CSS properties
https://bugs.webkit.org/show_bug.cgi?id=218902
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/Document-getAnimations.tentative-expected.txt (269812 => 269813)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/Document-getAnimations.tentative-expected.txt 2020-11-14 08:52:49 UTC (rev 269812)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/Document-getAnimations.tentative-expected.txt 2020-11-14 09:01:04 UTC (rev 269813)
@@ -16,5 +16,5 @@
PASS CSS Animations canceled and restarted via the API are returned
PASS pseudo element with replaced target does not affect animation ordering
PASS CSS Animations targetting (pseudo-)elements should have correct order after sorting
-FAIL CSS Animations targetting (pseudo-)elements should have correct order after sorting (::marker) assert_equals: CSS animations on both pseudo-elements and elements are returned expected 5 but got 4
+PASS CSS Animations targetting (pseudo-)elements should have correct order after sorting (::marker)
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/animationevent-marker-pseudoelement-expected.txt (269812 => 269813)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/animationevent-marker-pseudoelement-expected.txt 2020-11-14 08:52:49 UTC (rev 269812)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/animationevent-marker-pseudoelement-expected.txt 2020-11-14 09:01:04 UTC (rev 269813)
@@ -1,5 +1,3 @@
-Harness Error (TIMEOUT), message = null
+PASS AnimationEvent should have the correct pseudoElement memeber
-TIMEOUT AnimationEvent should have the correct pseudoElement memeber Test timed out
-
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/event-order.tentative-expected.txt (269812 => 269813)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/event-order.tentative-expected.txt 2020-11-14 08:52:49 UTC (rev 269812)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/event-order.tentative-expected.txt 2020-11-14 09:01:04 UTC (rev 269813)
@@ -1,7 +1,7 @@
PASS Same events are ordered by elements
PASS Same events on pseudo-elements follow the prescribed order
-FAIL Same events on pseudo-elements follow the prescribed order (::marker) assert_equals: Number of events received (4) should match expected number (5) (expected: animationstart, animationstart, animationstart, animationstart, animationstart, actual: animationstart, animationstart, animationstart, animationstart) expected 5 but got 4
+PASS Same events on pseudo-elements follow the prescribed order (::marker)
FAIL Start and iteration events are ordered by time assert_equals: Event #1 types should match (expected: animationiteration, animationstart, actual: animationstart, animationiteration) expected "animationiteration" but got "animationstart"
FAIL Iteration and end events are ordered by time assert_equals: Event #1 types should match (expected: animationiteration, animationend, actual: animationend, animationiteration) expected "animationiteration" but got "animationend"
FAIL Start and end events are sorted correctly when fired simultaneously assert_equals: Event #1 targets should match expected Element node <div style="animation: anim 100s 2"></div> but got Element node <div style="animation: anim 100s 100s"></div>
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-pseudo/marker-animate-expected.txt (269812 => 269813)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-pseudo/marker-animate-expected.txt 2020-11-14 08:52:49 UTC (rev 269812)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-pseudo/marker-animate-expected.txt 2020-11-14 09:01:04 UTC (rev 269813)
@@ -1,5 +1,5 @@
-FAIL 'color' animation assert_equals: color expected "rgb(100, 50, 150)" but got "rgb(0, 0, 0)"
-PASS 'opacity' animation
-FAIL 'color' + 'opacity' animation assert_equals: color expected "rgb(100, 50, 150)" but got "rgb(0, 0, 0)"
+PASS 'color' animation
+FAIL 'opacity' animation assert_equals: opacity expected "1" but got "0.5"
+FAIL 'color' + 'opacity' animation assert_equals: opacity expected "1" but got "0.5"
list item
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-pseudo/parsing/marker-supported-properties-in-animation-expected.txt (269812 => 269813)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-pseudo/parsing/marker-supported-properties-in-animation-expected.txt 2020-11-14 08:52:49 UTC (rev 269812)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-pseudo/parsing/marker-supported-properties-in-animation-expected.txt 2020-11-14 09:01:04 UTC (rev 269813)
@@ -1,12 +1,12 @@
-FAIL Animation of font in ::marker assert_in_array: value "normal normal normal normal 16px/normal -webkit-standard" not in array ["italic small-caps 500 expanded 15px Ahem", "italic small-caps 500 expanded 15px/normal Ahem"]
+FAIL Animation of font in ::marker assert_in_array: value "italic normal 500 expanded 15px/35px -webkit-standard" not in array ["italic small-caps 500 expanded 15px Ahem", "italic small-caps 500 expanded 15px/normal Ahem"]
FAIL Animation of font-family in ::marker assert_equals: expected "Ahem" but got "-webkit-standard"
FAIL Animation of font-feature-settings in ::marker assert_equals: expected "\"smcp\"" but got "normal"
FAIL Animation of font-kerning in ::marker assert_equals: expected "none" but got "auto"
-FAIL Animation of font-size in ::marker assert_equals: expected "15px" but got "16px"
+PASS Animation of font-size in ::marker
FAIL Animation of font-size-adjust in ::marker assert_true: font-size-adjust doesn't seem to be supported in the computed style expected true got false
-FAIL Animation of font-stretch in ::marker assert_in_array: value "normal" not in array ["expanded", "125%"]
-FAIL Animation of font-style in ::marker assert_equals: expected "italic" but got "normal"
+PASS Animation of font-stretch in ::marker
+PASS Animation of font-style in ::marker
FAIL Animation of font-synthesis in ::marker assert_equals: expected "none" but got "style weight small-caps"
FAIL Animation of font-variant in ::marker assert_equals: expected "small-caps" but got "tabular-nums"
FAIL Animation of font-variant-caps in ::marker assert_equals: expected "small-caps" but got "normal"
@@ -14,7 +14,7 @@
FAIL Animation of font-variant-ligatures in ::marker assert_equals: expected "historical-ligatures" but got "normal"
FAIL Animation of font-variant-numeric in ::marker assert_equals: expected "slashed-zero" but got "tabular-nums"
FAIL Animation of font-variant-position in ::marker assert_equals: expected "sub" but got "normal"
-FAIL Animation of font-weight in ::marker assert_equals: expected "500" but got "normal"
+PASS Animation of font-weight in ::marker
FAIL Animation of white-space in ::marker assert_equals: expected "nowrap" but got "normal"
FAIL Animation of color in ::marker assert_equals: expected "rgb(50, 150, 100)" but got "rgb(0, 0, 0)"
FAIL Animation of text-combine-upright in ::marker assert_true: text-combine-upright doesn't seem to be supported in the computed style expected true got false
@@ -28,14 +28,14 @@
PASS Animation of list-style-image in ::marker
PASS Animation of list-style-position in ::marker
PASS Animation of list-style-type in ::marker
-PASS Animation of line-height in ::marker
-FAIL Transition of font in ::marker assert_in_array: value "italic small-caps 900 ultra-expanded 25px/normal Ahem" not in array ["italic small-caps 500 expanded 15px Ahem", "italic small-caps 500 expanded 15px/normal Ahem"]
+FAIL Animation of line-height in ::marker assert_equals: expected "normal" but got "35px"
+FAIL Transition of font in ::marker assert_in_array: value "italic small-caps 500 expanded 15px/35px Ahem" not in array ["italic small-caps 500 expanded 15px Ahem", "italic small-caps 500 expanded 15px/normal Ahem"]
PASS Transition of font-family in ::marker
PASS Transition of font-feature-settings in ::marker
FAIL Transition of font-kerning in ::marker assert_equals: expected "none" but got "auto"
-FAIL Transition of font-size in ::marker assert_equals: expected "15px" but got "25px"
+PASS Transition of font-size in ::marker
FAIL Transition of font-size-adjust in ::marker assert_true: font-size-adjust doesn't seem to be supported in the computed style expected true got false
-FAIL Transition of font-stretch in ::marker assert_in_array: value "ultra-expanded" not in array ["expanded", "125%"]
+PASS Transition of font-stretch in ::marker
PASS Transition of font-style in ::marker
PASS Transition of font-synthesis in ::marker
PASS Transition of font-variant in ::marker
@@ -44,9 +44,9 @@
PASS Transition of font-variant-ligatures in ::marker
PASS Transition of font-variant-numeric in ::marker
PASS Transition of font-variant-position in ::marker
-FAIL Transition of font-weight in ::marker assert_equals: expected "500" but got "900"
+PASS Transition of font-weight in ::marker
FAIL Transition of white-space in ::marker assert_equals: expected "nowrap" but got "normal"
-FAIL Transition of color in ::marker assert_equals: expected "rgb(50, 150, 100)" but got "rgb(100, 200, 0)"
+PASS Transition of color in ::marker
FAIL Transition of text-combine-upright in ::marker assert_true: text-combine-upright doesn't seem to be supported in the computed style expected true got false
FAIL Transition of unicode-bidi in ::marker assert_equals: expected "plaintext" but got "normal"
FAIL Transition of direction in ::marker assert_equals: expected "rtl" but got "ltr"
@@ -58,5 +58,5 @@
PASS Transition of list-style-image in ::marker
PASS Transition of list-style-position in ::marker
PASS Transition of list-style-type in ::marker
-PASS Transition of line-height in ::marker
+FAIL Transition of line-height in ::marker assert_equals: expected "normal" but got "35px"
target
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-transitions/Document-getAnimations.tentative-expected.txt (269812 => 269813)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-transitions/Document-getAnimations.tentative-expected.txt 2020-11-14 08:52:49 UTC (rev 269812)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-transitions/Document-getAnimations.tentative-expected.txt 2020-11-14 09:01:04 UTC (rev 269813)
@@ -4,6 +4,6 @@
PASS getAnimations for CSS Transitions sort by property name
PASS getAnimations for CSS Transitions sort by transition generation
PASS CSS Transitions targetting (pseudo-)elements should have correct order after sorting
-FAIL CSS Transitions targetting (pseudo-)elements should have correct order after sorting (::marker) assert_equals: CSS transition on both pseudo-elements and elements are returned expected 5 but got 4
+PASS CSS Transitions targetting (pseudo-)elements should have correct order after sorting (::marker)
PASS Transitions are not returned after they have finished
Modified: trunk/Source/WebCore/ChangeLog (269812 => 269813)
--- trunk/Source/WebCore/ChangeLog 2020-11-14 08:52:49 UTC (rev 269812)
+++ trunk/Source/WebCore/ChangeLog 2020-11-14 09:01:04 UTC (rev 269813)
@@ -1,5 +1,61 @@
2020-11-13 Antoine Quint <[email protected]>
+ Support animations on more pseudo-elements
+ https://bugs.webkit.org/show_bug.cgi?id=218792
+ <rdar://problem/71274485>
+
+ Reviewed by Antti Koivisto.
+
+ We used to only support animations for pseudo-elements that were represented by PseudoElement (::before and ::after).
+ With this patch, we can now animate any public pseudo-element, such as ::marker.
+
+ * animation/KeyframeEffect.cpp:
+ (WebCore::elementOrPseudoElementForStyleable): For pseudo-elements other than ::before or ::after, return the Styleable's
+ element since a PseudoElement is only accessible for the aforementioned pseudo-elements.
+ (WebCore::KeyframeEffect::targetElementOrPseudoElement const): For pseudo-elements other than ::before or ::after, return
+ the animation target as the target element.
+ * dom/PseudoElement.cpp:
+ (WebCore::PseudoElement::rendererIsNeeded): Refactor what was originally isTargetedByKeyframeEffectRequiringPseudoElement()
+ into this method since isTargetedByKeyframeEffectRequiringPseudoElement() was removed.
+ (WebCore::PseudoElement::isTargetedByKeyframeEffectRequiringPseudoElement): Remove this method from PseudoElement since
+ pseudo-elements that are not represented by a PseudoElement need similar logic, which is now available through the static
+ function elementIsTargetedByKeyframeEffectRequiringPseudoElement() in RenderTreeUpdaterGeneratedContent.cpp.
+ * dom/PseudoElement.h:
+ * rendering/updating/RenderTreeUpdater.cpp:
+ (WebCore::RenderTreeUpdater::updateRenderTree): Pass the entire set of ElementUpdates instead of just the ElementUpdate to
+ updateElementRenderer() such that it may process the new pseudoElementUpdates member.
+ (WebCore::RenderTreeUpdater::updateBeforeDescendants): Pass the entire set of ElementUpdates and a PseudoId to
+ updatePseudoElement() such that it may use the new pseudoElementUpdates member in combination with the PseudoId
+ to determine what ElementUpdate to use.
+ (WebCore::RenderTreeUpdater::updateAfterDescendants): Pass the entire set of ElementUpdates and a PseudoId to
+ updatePseudoElement() such that it may use the new pseudoElementUpdates member in combination with the PseudoId
+ to determine what ElementUpdate to use.
+ (WebCore::RenderTreeUpdater::updateElementRenderer): Use the new pseudoElementUpdates member in ElementUpdates to set the
+ pseudo-element styles.
+ * rendering/updating/RenderTreeUpdater.h:
+ * rendering/updating/RenderTreeUpdaterGeneratedContent.cpp:
+ (WebCore::elementIsTargetedByKeyframeEffectRequiringPseudoElement): New static method meant to replace the removed
+ PseudoElement::isTargetedByKeyframeEffectRequiringPseudoElement() such that we may use this method regardless of whether
+ the pseudo-element is represented by PseudoElement.
+ (WebCore::createContentRenderers): Use elementIsTargetedByKeyframeEffectRequiringPseudoElement() instead of the removed
+ PseudoElement::isTargetedByKeyframeEffectRequiringPseudoElement().
+ (WebCore::RenderTreeUpdater::GeneratedContent::updatePseudoElement): Look up all ElementUpdate for the provided PseudoId
+ in the new pseudoElementUpdates member in ElementUpdates in order to determine what ElementUpdate to process. Also, use
+ elementIsTargetedByKeyframeEffectRequiringPseudoElement() instead of the removed
+ PseudoElement::isTargetedByKeyframeEffectRequiringPseudoElement().
+ (WebCore::RenderTreeUpdater::GeneratedContent::needsPseudoElement):
+ * rendering/updating/RenderTreeUpdaterGeneratedContent.h:
+ * style/StyleTreeResolver.cpp:
+ (WebCore::Style::TreeResolver::resolveElement): Resolve any public pseudo-element instead of just ::before and ::after
+ and save those in the new ElementUpdates pseudoElementUpdates member.
+ (WebCore::Style::TreeResolver::resolvePseudoStyle): Resolve any pseudo-element set on an element that either has animations
+ set on it, either set by Web Animations, as seen on the KeyframeEffectStack, or yet to be applied through a CSS Animation or
+ CSS Transition, as seen on the RenderStyle.
+ * style/StyleTreeResolver.h:
+ * style/StyleUpdate.h: Add a new pseudoElementUpdates member on ElementUpdates.
+
+2020-11-13 Antoine Quint <[email protected]>
+
Add support for discrete animations of many CSS properties
https://bugs.webkit.org/show_bug.cgi?id=218902
Modified: trunk/Source/WebCore/animation/KeyframeEffect.cpp (269812 => 269813)
--- trunk/Source/WebCore/animation/KeyframeEffect.cpp 2020-11-14 08:52:49 UTC (rev 269812)
+++ trunk/Source/WebCore/animation/KeyframeEffect.cpp 2020-11-14 09:01:04 UTC (rev 269813)
@@ -72,14 +72,12 @@
return nullptr;
switch (styleable->pseudoId) {
- case PseudoId::None:
- return &styleable->element;
case PseudoId::Before:
return styleable->element.beforePseudoElement();
case PseudoId::After:
return styleable->element.afterPseudoElement();
default:
- return nullptr;
+ return &styleable->element;
}
}
@@ -1147,17 +1145,15 @@
Element* KeyframeEffect::targetElementOrPseudoElement() const
{
- if (!targetsPseudoElement())
- return m_target.get();
+ if (m_target) {
+ if (m_pseudoId == PseudoId::Before)
+ return m_target->beforePseudoElement();
- if (m_pseudoId == PseudoId::Before)
- return m_target->beforePseudoElement();
+ if (m_pseudoId == PseudoId::After)
+ return m_target->afterPseudoElement();
+ }
- if (m_pseudoId == PseudoId::After)
- return m_target->afterPseudoElement();
-
- // We only support targeting ::before and ::after pseudo-elements at the moment.
- return nullptr;
+ return m_target.get();
}
void KeyframeEffect::setTarget(RefPtr<Element>&& newTarget)
Modified: trunk/Source/WebCore/dom/PseudoElement.cpp (269812 => 269813)
--- trunk/Source/WebCore/dom/PseudoElement.cpp 2020-11-14 08:52:49 UTC (rev 269812)
+++ trunk/Source/WebCore/dom/PseudoElement.cpp 2020-11-14 09:01:04 UTC (rev 269813)
@@ -83,11 +83,9 @@
bool PseudoElement::rendererIsNeeded(const RenderStyle& style)
{
- return pseudoElementRendererIsNeeded(&style) || isTargetedByKeyframeEffectRequiringPseudoElement();
-}
+ if (pseudoElementRendererIsNeeded(&style))
+ return true;
-bool PseudoElement::isTargetedByKeyframeEffectRequiringPseudoElement()
-{
if (m_hostElement) {
if (auto* stack = m_hostElement->keyframeEffectStack(pseudoId()))
return stack->requiresPseudoElement();
Modified: trunk/Source/WebCore/dom/PseudoElement.h (269812 => 269813)
--- trunk/Source/WebCore/dom/PseudoElement.h 2020-11-14 08:52:49 UTC (rev 269812)
+++ trunk/Source/WebCore/dom/PseudoElement.h 2020-11-14 09:01:04 UTC (rev 269813)
@@ -41,7 +41,6 @@
void clearHostElement();
bool rendererIsNeeded(const RenderStyle&) override;
- bool isTargetedByKeyframeEffectRequiringPseudoElement();
bool canStartSelection() const override { return false; }
bool canContainRangeEndPoint() const override { return false; }
Modified: trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.cpp (269812 => 269813)
--- trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.cpp 2020-11-14 08:52:49 UTC (rev 269812)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.cpp 2020-11-14 09:01:04 UTC (rev 269813)
@@ -191,7 +191,7 @@
}
if (elementUpdates)
- updateElementRenderer(element, elementUpdates->update);
+ updateElementRenderer(element, *elementUpdates);
storePreviousRenderer(element);
@@ -251,13 +251,13 @@
void RenderTreeUpdater::updateBeforeDescendants(Element& element, const Style::ElementUpdates* updates)
{
if (updates)
- generatedContent().updatePseudoElement(element, updates->beforePseudoElementUpdate, PseudoId::Before);
+ generatedContent().updatePseudoElement(element, *updates, PseudoId::Before);
}
void RenderTreeUpdater::updateAfterDescendants(Element& element, const Style::ElementUpdates* updates)
{
if (updates)
- generatedContent().updatePseudoElement(element, updates->afterPseudoElementUpdate, PseudoId::After);
+ generatedContent().updatePseudoElement(element, *updates, PseudoId::After);
auto* renderer = element.renderer();
if (!renderer)
@@ -297,13 +297,23 @@
m_builder.normalizeTreeAfterStyleChange(renderer, oldStyle);
}
-void RenderTreeUpdater::updateElementRenderer(Element& element, const Style::ElementUpdate& update)
+void RenderTreeUpdater::updateElementRenderer(Element& element, const Style::ElementUpdates& updates)
{
#if PLATFORM(IOS_FAMILY)
ContentChangeObserver::StyleChangeScope observingScope(m_document, element);
#endif
- bool shouldTearDownRenderers = update.change == Style::Change::Renderer && (element.renderer() || element.hasDisplayContents());
+ auto& elementUpdate = updates.update;
+ auto elementUpdateStyle = RenderStyle::clonePtr(*elementUpdate.style);
+
+ for (auto& it : updates.pseudoElementUpdates) {
+ auto pseudoId = it.key;
+ if (pseudoId == PseudoId::Before || pseudoId == PseudoId::After)
+ continue;
+ elementUpdateStyle->addCachedPseudoStyle(RenderStyle::clonePtr(*it.value.style));
+ }
+
+ bool shouldTearDownRenderers = elementUpdate.change == Style::Change::Renderer && (element.renderer() || element.hasDisplayContents());
if (shouldTearDownRenderers) {
if (!element.renderer()) {
// We may be tearing down a descendant renderer cached in renderTreePosition.
@@ -311,15 +321,15 @@
}
// display:none cancels animations.
- auto teardownType = update.style->display() == DisplayType::None ? TeardownType::RendererUpdateCancelingAnimations : TeardownType::RendererUpdate;
+ auto teardownType = elementUpdate.style->display() == DisplayType::None ? TeardownType::RendererUpdateCancelingAnimations : TeardownType::RendererUpdate;
tearDownRenderers(element, teardownType, m_builder);
renderingParent().didCreateOrDestroyChildRenderer = true;
}
- bool hasDisplayContents = update.style->display() == DisplayType::Contents;
+ bool hasDisplayContents = elementUpdate.style->display() == DisplayType::Contents;
if (hasDisplayContents)
- element.storeDisplayContentsStyle(RenderStyle::clonePtr(*update.style));
+ element.storeDisplayContentsStyle(WTFMove(elementUpdateStyle));
else
element.resetComputedStyle();
@@ -327,7 +337,7 @@
if (shouldCreateNewRenderer) {
if (element.hasCustomStyleResolveCallbacks())
element.willAttachRenderers();
- createRenderer(element, RenderStyle::clone(*update.style));
+ createRenderer(element, WTFMove(*elementUpdateStyle));
renderingParent().didCreateOrDestroyChildRenderer = true;
return;
@@ -337,20 +347,20 @@
return;
auto& renderer = *element.renderer();
- if (update.recompositeLayer) {
- updateRendererStyle(renderer, RenderStyle::clone(*update.style), StyleDifference::RecompositeLayer);
+ if (elementUpdate.recompositeLayer) {
+ updateRendererStyle(renderer, WTFMove(*elementUpdateStyle), StyleDifference::RecompositeLayer);
return;
}
- if (update.change == Style::Change::None) {
- if (pseudoStyleCacheIsInvalid(&renderer, update.style.get())) {
- updateRendererStyle(renderer, RenderStyle::clone(*update.style), StyleDifference::Equal);
+ if (elementUpdate.change == Style::Change::None) {
+ if (pseudoStyleCacheIsInvalid(&renderer, elementUpdateStyle.get())) {
+ updateRendererStyle(renderer, WTFMove(*elementUpdateStyle), StyleDifference::Equal);
return;
}
return;
}
- updateRendererStyle(renderer, RenderStyle::clone(*update.style), StyleDifference::Equal);
+ updateRendererStyle(renderer, WTFMove(*elementUpdateStyle), StyleDifference::Equal);
}
void RenderTreeUpdater::createRenderer(Element& element, RenderStyle&& style)
Modified: trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.h (269812 => 269813)
--- trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.h 2020-11-14 08:52:49 UTC (rev 269812)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.h 2020-11-14 09:01:04 UTC (rev 269813)
@@ -58,7 +58,7 @@
void updateRenderTree(ContainerNode& root);
void updateTextRenderer(Text&, const Style::TextUpdate*);
void createTextRenderer(Text&, const Style::TextUpdate*);
- void updateElementRenderer(Element&, const Style::ElementUpdate&);
+ void updateElementRenderer(Element&, const Style::ElementUpdates&);
void updateRendererStyle(RenderElement&, RenderStyle&&, StyleDifference);
void createRenderer(Element&, RenderStyle&&);
void updateBeforeDescendants(Element&, const Style::ElementUpdates*);
Modified: trunk/Source/WebCore/rendering/updating/RenderTreeUpdaterGeneratedContent.cpp (269812 => 269813)
--- trunk/Source/WebCore/rendering/updating/RenderTreeUpdaterGeneratedContent.cpp 2020-11-14 08:52:49 UTC (rev 269812)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeUpdaterGeneratedContent.cpp 2020-11-14 09:01:04 UTC (rev 269813)
@@ -69,8 +69,21 @@
ASSERT(!lastQuote);
}
-static void createContentRenderers(RenderTreeBuilder& builder, RenderElement& pseudoRenderer, const RenderStyle& style)
+static bool elementIsTargetedByKeyframeEffectRequiringPseudoElement(const Element* element, PseudoId pseudoId)
{
+ if (is<PseudoElement>(element))
+ return elementIsTargetedByKeyframeEffectRequiringPseudoElement(downcast<PseudoElement>(*element).hostElement(), pseudoId);
+
+ if (element) {
+ if (auto* stack = element->keyframeEffectStack(pseudoId))
+ return stack->requiresPseudoElement();
+ }
+
+ return false;
+}
+
+static void createContentRenderers(RenderTreeBuilder& builder, RenderElement& pseudoRenderer, const RenderStyle& style, PseudoId pseudoId)
+{
if (auto* contentData = style.contentData()) {
for (const ContentData* content = contentData; content; content = content->next()) {
auto child = content->createContentRenderer(pseudoRenderer.document(), style);
@@ -80,7 +93,7 @@
} else {
// The only valid scenario where this method is called without the "content" property being set
// is the case where a pseudo-element has animations set on it via the Web Animations API.
- ASSERT(is<PseudoElement>(pseudoRenderer.element()) && downcast<PseudoElement>(*pseudoRenderer.element()).isTargetedByKeyframeEffectRequiringPseudoElement());
+ ASSERT_UNUSED(pseudoId, elementIsTargetedByKeyframeEffectRequiringPseudoElement(pseudoRenderer.element(), pseudoId));
}
}
@@ -94,7 +107,7 @@
}
}
-void RenderTreeUpdater::GeneratedContent::updatePseudoElement(Element& current, const Optional<Style::ElementUpdate>& update, PseudoId pseudoId)
+void RenderTreeUpdater::GeneratedContent::updatePseudoElement(Element& current, const Style::ElementUpdates& updates, PseudoId pseudoId)
{
PseudoElement* pseudoElement = pseudoId == PseudoId::Before ? current.beforePseudoElement() : current.afterPseudoElement();
@@ -101,7 +114,14 @@
if (auto* renderer = pseudoElement ? pseudoElement->renderer() : nullptr)
m_updater.renderTreePosition().invalidateNextSibling(*renderer);
- if (!needsPseudoElement(update) && (!pseudoElement || !pseudoElement->isTargetedByKeyframeEffectRequiringPseudoElement())) {
+ auto* update = [&]() -> const Style::ElementUpdate* {
+ auto iterator = updates.pseudoElementUpdates.find(pseudoId);
+ if (iterator != updates.pseudoElementUpdates.end())
+ return &iterator->value;
+ return nullptr;
+ }();
+
+ if (!needsPseudoElement(update) && (!pseudoElement || !elementIsTargetedByKeyframeEffectRequiringPseudoElement(pseudoElement, pseudoId))) {
if (pseudoElement) {
if (pseudoId == PseudoId::Before)
removeBeforePseudoElement(current, m_updater.m_builder);
@@ -111,7 +131,7 @@
return;
}
- if (update->change == Style::Change::None)
+ if (!update || update->change == Style::Change::None)
return;
pseudoElement = ¤t.ensurePseudoElement(pseudoId);
@@ -125,10 +145,14 @@
contentsStyle->copyContentFrom(*update->style);
Style::ElementUpdate contentsUpdate { WTFMove(contentsStyle), update->change, update->recompositeLayer };
- m_updater.updateElementRenderer(*pseudoElement, contentsUpdate);
+ Style::ElementUpdates contentsUpdates { WTFMove(contentsUpdate), Style::DescendantsToResolve::None, { } };
+ m_updater.updateElementRenderer(*pseudoElement, WTFMove(contentsUpdates));
pseudoElement->storeDisplayContentsStyle(RenderStyle::clonePtr(*update->style));
} else {
- m_updater.updateElementRenderer(*pseudoElement, *update);
+ auto pseudoElementUpdateStyle = RenderStyle::clonePtr(*update->style);
+ Style::ElementUpdate pseudoElementUpdate { WTFMove(pseudoElementUpdateStyle), update->change, update->recompositeLayer };
+ Style::ElementUpdates pseudoElementUpdates { WTFMove(pseudoElementUpdate), Style::DescendantsToResolve::None, { } };
+ m_updater.updateElementRenderer(*pseudoElement, WTFMove(pseudoElementUpdates));
ASSERT(!pseudoElement->hasDisplayContents());
}
@@ -137,7 +161,7 @@
return;
if (update->change == Style::Change::Renderer)
- createContentRenderers(m_updater.m_builder, *pseudoElementRenderer, *update->style);
+ createContentRenderers(m_updater.m_builder, *pseudoElementRenderer, *update->style, pseudoId);
else
updateStyleForContentRenderers(*pseudoElementRenderer, *update->style);
@@ -148,7 +172,7 @@
m_updater.m_builder.updateAfterDescendants(*pseudoElementRenderer);
}
-bool RenderTreeUpdater::GeneratedContent::needsPseudoElement(const Optional<Style::ElementUpdate>& update)
+bool RenderTreeUpdater::GeneratedContent::needsPseudoElement(const Style::ElementUpdate* update)
{
if (!update)
return false;
Modified: trunk/Source/WebCore/rendering/updating/RenderTreeUpdaterGeneratedContent.h (269812 => 269813)
--- trunk/Source/WebCore/rendering/updating/RenderTreeUpdaterGeneratedContent.h 2020-11-14 08:52:49 UTC (rev 269812)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeUpdaterGeneratedContent.h 2020-11-14 09:01:04 UTC (rev 269813)
@@ -38,7 +38,7 @@
public:
GeneratedContent(RenderTreeUpdater&);
- void updatePseudoElement(Element&, const Optional<Style::ElementUpdate>&, PseudoId);
+ void updatePseudoElement(Element&, const Style::ElementUpdates&, PseudoId);
void updateRemainingQuotes();
static void removeBeforePseudoElement(Element&, RenderTreeBuilder&);
@@ -47,7 +47,7 @@
private:
void updateQuotesUpTo(RenderQuote*);
- bool needsPseudoElement(const Optional<Style::ElementUpdate>&);
+ bool needsPseudoElement(const Style::ElementUpdate*);
RenderTreeUpdater& m_updater;
WeakPtr<RenderQuote> m_previousUpdatedQuote;
Modified: trunk/Source/WebCore/style/StyleTreeResolver.cpp (269812 => 269813)
--- trunk/Source/WebCore/style/StyleTreeResolver.cpp 2020-11-14 08:52:49 UTC (rev 269812)
+++ trunk/Source/WebCore/style/StyleTreeResolver.cpp 2020-11-14 09:01:04 UTC (rev 269813)
@@ -54,6 +54,7 @@
#include "StyleScope.h"
#include "Text.h"
#include "WebAnimationTypes.h"
+#include "WebAnimationUtilities.h"
namespace WebCore {
@@ -244,8 +245,11 @@
}
}
- auto beforeUpdate = resolvePseudoStyle(element, update, PseudoId::Before);
- auto afterUpdate = resolvePseudoStyle(element, update, PseudoId::After);
+ PseudoIdToElementUpdateMap pseudoUpdates;
+ for (PseudoId pseudoId = PseudoId::FirstPublicPseudoId; pseudoId < PseudoId::FirstInternalPseudoId; pseudoId = static_cast<PseudoId>(static_cast<unsigned>(pseudoId) + 1)) {
+ if (auto elementUpdate = resolvePseudoStyle(element, update, pseudoId))
+ pseudoUpdates.set(pseudoId, WTFMove(*elementUpdate));
+ }
#if ENABLE(TOUCH_ACTION_REGIONS)
// FIXME: Track this exactly.
@@ -257,11 +261,13 @@
m_document.setMayHaveEditableElements();
#endif
- return { WTFMove(update), descendantsToResolve, WTFMove(beforeUpdate), WTFMove(afterUpdate) };
+ return { WTFMove(update), descendantsToResolve, WTFMove(pseudoUpdates) };
}
-ElementUpdate TreeResolver::resolvePseudoStyle(Element& element, const ElementUpdate& elementUpdate, PseudoId pseudoId)
+Optional<ElementUpdate> TreeResolver::resolvePseudoStyle(Element& element, const ElementUpdate& elementUpdate, PseudoId pseudoId)
{
+ if (pseudoId == PseudoId::Marker && elementUpdate.style->display() != DisplayType::ListItem)
+ return { };
if (elementUpdate.style->display() == DisplayType::None)
return { };
if (!elementUpdate.style->hasPseudoStyle(pseudoId))
@@ -271,8 +277,7 @@
if (!pseudoStyle)
return { };
- auto* pseudoElement = pseudoId == PseudoId::Before ? element.beforePseudoElement() : element.afterPseudoElement();
- bool hasAnimations = pseudoElement && pseudoElement->isTargetedByKeyframeEffectRequiringPseudoElement();
+ bool hasAnimations = pseudoStyle->hasAnimationsOrTransitions() || element.hasKeyframeEffects(pseudoId);
if (!pseudoElementRendererIsNeeded(pseudoStyle.get()) && !hasAnimations)
return { };
Modified: trunk/Source/WebCore/style/StyleTreeResolver.h (269812 => 269813)
--- trunk/Source/WebCore/style/StyleTreeResolver.h 2020-11-14 08:52:49 UTC (rev 269812)
+++ trunk/Source/WebCore/style/StyleTreeResolver.h 2020-11-14 09:01:04 UTC (rev 269813)
@@ -62,7 +62,7 @@
ElementUpdates resolveElement(Element&);
ElementUpdate createAnimatedElementUpdate(std::unique_ptr<RenderStyle>, const Styleable&, Change);
- ElementUpdate resolvePseudoStyle(Element&, const ElementUpdate&, PseudoId);
+ Optional<ElementUpdate> resolvePseudoStyle(Element&, const ElementUpdate&, PseudoId);
struct Scope : RefCounted<Scope> {
WTF_MAKE_STRUCT_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(TreeResolverScope);
Modified: trunk/Source/WebCore/style/StyleUpdate.h (269812 => 269813)
--- trunk/Source/WebCore/style/StyleUpdate.h 2020-11-14 08:52:49 UTC (rev 269812)
+++ trunk/Source/WebCore/style/StyleUpdate.h 2020-11-14 09:01:04 UTC (rev 269813)
@@ -50,11 +50,12 @@
enum class DescendantsToResolve { None, ChildrenWithExplicitInherit, Children, All };
+using PseudoIdToElementUpdateMap = HashMap<PseudoId, ElementUpdate, WTF::IntHash<PseudoId>, WTF::StrongEnumHashTraits<PseudoId>>;
+
struct ElementUpdates {
ElementUpdate update;
DescendantsToResolve descendantsToResolve { DescendantsToResolve::None };
- Optional<ElementUpdate> beforePseudoElementUpdate;
- Optional<ElementUpdate> afterPseudoElementUpdate;
+ PseudoIdToElementUpdateMap pseudoElementUpdates;
};
struct TextUpdate {