Title: [269813] trunk
Revision
269813
Author
[email protected]
Date
2020-11-14 01:01:04 -0800 (Sat, 14 Nov 2020)

Log Message

Support animations on more pseudo-elements
https://bugs.webkit.org/show_bug.cgi?id=218792
<rdar://problem/71274485>

Reviewed by Antti Koivisto.

LayoutTests/imported/w3c:

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:

Source/WebCore:

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.

Modified Paths

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 = &current.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 {
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to