<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[269813] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/269813">269813</a></dd>
<dt>Author</dt> <dd>graouts@webkit.org</dd>
<dt>Date</dt> <dd>2020-11-14 01:01:04 -0800 (Sat, 14 Nov 2020)</dd>
</dl>

<h3>Log Message</h3>
<pre>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.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsimportedw3cChangeLog">trunk/LayoutTests/imported/w3c/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestscsscssanimationsDocumentgetAnimationstentativeexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/Document-getAnimations.tentative-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestscsscssanimationsanimationeventmarkerpseudoelementexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/animationevent-marker-pseudoelement-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestscsscssanimationseventordertentativeexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/event-order.tentative-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestscsscsspseudomarkeranimateexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-pseudo/marker-animate-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestscsscsspseudoparsingmarkersupportedpropertiesinanimationexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-pseudo/parsing/marker-supported-properties-in-animation-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestscsscsstransitionsDocumentgetAnimationstentativeexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-transitions/Document-getAnimations.tentative-expected.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreanimationKeyframeEffectcpp">trunk/Source/WebCore/animation/KeyframeEffect.cpp</a></li>
<li><a href="#trunkSourceWebCoredomPseudoElementcpp">trunk/Source/WebCore/dom/PseudoElement.cpp</a></li>
<li><a href="#trunkSourceWebCoredomPseudoElementh">trunk/Source/WebCore/dom/PseudoElement.h</a></li>
<li><a href="#trunkSourceWebCorerenderingupdatingRenderTreeUpdatercpp">trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingupdatingRenderTreeUpdaterh">trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.h</a></li>
<li><a href="#trunkSourceWebCorerenderingupdatingRenderTreeUpdaterGeneratedContentcpp">trunk/Source/WebCore/rendering/updating/RenderTreeUpdaterGeneratedContent.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingupdatingRenderTreeUpdaterGeneratedContenth">trunk/Source/WebCore/rendering/updating/RenderTreeUpdaterGeneratedContent.h</a></li>
<li><a href="#trunkSourceWebCorestyleStyleTreeResolvercpp">trunk/Source/WebCore/style/StyleTreeResolver.cpp</a></li>
<li><a href="#trunkSourceWebCorestyleStyleTreeResolverh">trunk/Source/WebCore/style/StyleTreeResolver.h</a></li>
<li><a href="#trunkSourceWebCorestyleStyleUpdateh">trunk/Source/WebCore/style/StyleUpdate.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsimportedw3cChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/ChangeLog (269812 => 269813)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,5 +1,22 @@
</span><span class="cx"> 2020-11-13  Antoine Quint  <graouts@webkit.org>
</span><span class="cx"> 
</span><ins>+        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  <graouts@webkit.org>
+
</ins><span class="cx">         Add support for discrete animations of many CSS properties
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=218902
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestscsscssanimationsDocumentgetAnimationstentativeexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/Document-getAnimations.tentative-expected.txt (269812 => 269813)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -16,5 +16,5 @@
</span><span class="cx"> PASS CSS Animations canceled and restarted via the API are returned
</span><span class="cx"> PASS pseudo element with replaced target does not affect animation ordering
</span><span class="cx"> PASS CSS Animations targetting (pseudo-)elements should have correct order after sorting
</span><del>-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
</del><ins>+PASS CSS Animations targetting (pseudo-)elements should have correct order after sorting (::marker)
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestscsscssanimationsanimationeventmarkerpseudoelementexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/animationevent-marker-pseudoelement-expected.txt (269812 => 269813)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,5 +1,3 @@
</span><span class="cx"> 
</span><del>-Harness Error (TIMEOUT), message = null
</del><ins>+PASS AnimationEvent should have the correct pseudoElement memeber
</ins><span class="cx"> 
</span><del>-TIMEOUT AnimationEvent should have the correct pseudoElement memeber Test timed out
-
</del></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestscsscssanimationseventordertentativeexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/event-order.tentative-expected.txt (269812 => 269813)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> 
</span><span class="cx"> PASS Same events are ordered by elements
</span><span class="cx"> PASS Same events on pseudo-elements follow the prescribed order
</span><del>-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
</del><ins>+PASS Same events on pseudo-elements follow the prescribed order (::marker)
</ins><span class="cx"> 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"
</span><span class="cx"> 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"
</span><span class="cx"> 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>
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestscsscsspseudomarkeranimateexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-pseudo/marker-animate-expected.txt (269812 => 269813)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> 
</span><del>-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)"
</del><ins>+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"
</ins><span class="cx"> list item
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestscsscsspseudoparsingmarkersupportedpropertiesinanimationexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-pseudo/parsing/marker-supported-properties-in-animation-expected.txt (269812 => 269813)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,12 +1,12 @@
</span><span class="cx"> 
</span><del>-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"]
</del><ins>+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"]
</ins><span class="cx"> FAIL Animation of font-family in ::marker assert_equals: expected "Ahem" but got "-webkit-standard"
</span><span class="cx"> FAIL Animation of font-feature-settings in ::marker assert_equals: expected "\"smcp\"" but got "normal"
</span><span class="cx"> FAIL Animation of font-kerning in ::marker assert_equals: expected "none" but got "auto"
</span><del>-FAIL Animation of font-size in ::marker assert_equals: expected "15px" but got "16px"
</del><ins>+PASS Animation of font-size in ::marker
</ins><span class="cx"> 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
</span><del>-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"
</del><ins>+PASS Animation of font-stretch in ::marker
+PASS Animation of font-style in ::marker
</ins><span class="cx"> FAIL Animation of font-synthesis in ::marker assert_equals: expected "none" but got "style weight small-caps"
</span><span class="cx"> FAIL Animation of font-variant in ::marker assert_equals: expected "small-caps" but got "tabular-nums"
</span><span class="cx"> FAIL Animation of font-variant-caps in ::marker assert_equals: expected "small-caps" but got "normal"
</span><span class="lines">@@ -14,7 +14,7 @@
</span><span class="cx"> FAIL Animation of font-variant-ligatures in ::marker assert_equals: expected "historical-ligatures" but got "normal"
</span><span class="cx"> FAIL Animation of font-variant-numeric in ::marker assert_equals: expected "slashed-zero" but got "tabular-nums"
</span><span class="cx"> FAIL Animation of font-variant-position in ::marker assert_equals: expected "sub" but got "normal"
</span><del>-FAIL Animation of font-weight in ::marker assert_equals: expected "500" but got "normal"
</del><ins>+PASS Animation of font-weight in ::marker
</ins><span class="cx"> FAIL Animation of white-space in ::marker assert_equals: expected "nowrap" but got "normal"
</span><span class="cx"> FAIL Animation of color in ::marker assert_equals: expected "rgb(50, 150, 100)" but got "rgb(0, 0, 0)"
</span><span class="cx"> 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
</span><span class="lines">@@ -28,14 +28,14 @@
</span><span class="cx"> PASS Animation of list-style-image in ::marker
</span><span class="cx"> PASS Animation of list-style-position in ::marker
</span><span class="cx"> PASS Animation of list-style-type in ::marker
</span><del>-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"]
</del><ins>+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"]
</ins><span class="cx"> PASS Transition of font-family in ::marker
</span><span class="cx"> PASS Transition of font-feature-settings in ::marker
</span><span class="cx"> FAIL Transition of font-kerning in ::marker assert_equals: expected "none" but got "auto"
</span><del>-FAIL Transition of font-size in ::marker assert_equals: expected "15px" but got "25px"
</del><ins>+PASS Transition of font-size in ::marker
</ins><span class="cx"> 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
</span><del>-FAIL Transition of font-stretch in ::marker assert_in_array: value "ultra-expanded" not in array ["expanded", "125%"]
</del><ins>+PASS Transition of font-stretch in ::marker
</ins><span class="cx"> PASS Transition of font-style in ::marker
</span><span class="cx"> PASS Transition of font-synthesis in ::marker
</span><span class="cx"> PASS Transition of font-variant in ::marker
</span><span class="lines">@@ -44,9 +44,9 @@
</span><span class="cx"> PASS Transition of font-variant-ligatures in ::marker
</span><span class="cx"> PASS Transition of font-variant-numeric in ::marker
</span><span class="cx"> PASS Transition of font-variant-position in ::marker
</span><del>-FAIL Transition of font-weight in ::marker assert_equals: expected "500" but got "900"
</del><ins>+PASS Transition of font-weight in ::marker
</ins><span class="cx"> FAIL Transition of white-space in ::marker assert_equals: expected "nowrap" but got "normal"
</span><del>-FAIL Transition of color in ::marker assert_equals: expected "rgb(50, 150, 100)" but got "rgb(100, 200, 0)"
</del><ins>+PASS Transition of color in ::marker
</ins><span class="cx"> 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
</span><span class="cx"> FAIL Transition of unicode-bidi in ::marker assert_equals: expected "plaintext" but got "normal"
</span><span class="cx"> FAIL Transition of direction in ::marker assert_equals: expected "rtl" but got "ltr"
</span><span class="lines">@@ -58,5 +58,5 @@
</span><span class="cx"> PASS Transition of list-style-image in ::marker
</span><span class="cx"> PASS Transition of list-style-position in ::marker
</span><span class="cx"> PASS Transition of list-style-type in ::marker
</span><del>-PASS Transition of line-height in ::marker
</del><ins>+FAIL Transition of line-height in ::marker assert_equals: expected "normal" but got "35px"
</ins><span class="cx"> target
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestscsscsstransitionsDocumentgetAnimationstentativeexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-transitions/Document-getAnimations.tentative-expected.txt (269812 => 269813)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -4,6 +4,6 @@
</span><span class="cx"> PASS getAnimations for CSS Transitions sort by property name
</span><span class="cx"> PASS getAnimations for CSS Transitions sort by transition generation
</span><span class="cx"> PASS CSS Transitions targetting (pseudo-)elements should have correct order after sorting
</span><del>-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
</del><ins>+PASS CSS Transitions targetting (pseudo-)elements should have correct order after sorting (::marker)
</ins><span class="cx"> PASS Transitions are not returned after they have finished
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (269812 => 269813)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,5 +1,61 @@
</span><span class="cx"> 2020-11-13  Antoine Quint  <graouts@webkit.org>
</span><span class="cx"> 
</span><ins>+        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  <graouts@webkit.org>
+
</ins><span class="cx">         Add support for discrete animations of many CSS properties
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=218902
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreanimationKeyframeEffectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/animation/KeyframeEffect.cpp (269812 => 269813)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -72,14 +72,12 @@
</span><span class="cx">         return nullptr;
</span><span class="cx"> 
</span><span class="cx">     switch (styleable->pseudoId) {
</span><del>-    case PseudoId::None:
-        return &styleable->element;
</del><span class="cx">     case PseudoId::Before:
</span><span class="cx">         return styleable->element.beforePseudoElement();
</span><span class="cx">     case PseudoId::After:
</span><span class="cx">         return styleable->element.afterPseudoElement();
</span><span class="cx">     default:
</span><del>-        return nullptr;
</del><ins>+        return &styleable->element;
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1147,17 +1145,15 @@
</span><span class="cx"> 
</span><span class="cx"> Element* KeyframeEffect::targetElementOrPseudoElement() const
</span><span class="cx"> {
</span><del>-    if (!targetsPseudoElement())
-        return m_target.get();
</del><ins>+    if (m_target) {
+        if (m_pseudoId == PseudoId::Before)
+            return m_target->beforePseudoElement();
</ins><span class="cx"> 
</span><del>-    if (m_pseudoId == PseudoId::Before)
-        return m_target->beforePseudoElement();
</del><ins>+        if (m_pseudoId == PseudoId::After)
+            return m_target->afterPseudoElement();
+    }
</ins><span class="cx"> 
</span><del>-    if (m_pseudoId == PseudoId::After)
-        return m_target->afterPseudoElement();
-
-    // We only support targeting ::before and ::after pseudo-elements at the moment.
-    return nullptr;
</del><ins>+    return m_target.get();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void KeyframeEffect::setTarget(RefPtr<Element>&& newTarget)
</span></span></pre></div>
<a id="trunkSourceWebCoredomPseudoElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/PseudoElement.cpp (269812 => 269813)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -83,11 +83,9 @@
</span><span class="cx"> 
</span><span class="cx"> bool PseudoElement::rendererIsNeeded(const RenderStyle& style)
</span><span class="cx"> {
</span><del>-    return pseudoElementRendererIsNeeded(&style) || isTargetedByKeyframeEffectRequiringPseudoElement();
-}
</del><ins>+    if (pseudoElementRendererIsNeeded(&style))
+        return true;
</ins><span class="cx"> 
</span><del>-bool PseudoElement::isTargetedByKeyframeEffectRequiringPseudoElement()
-{
</del><span class="cx">     if (m_hostElement) {
</span><span class="cx">         if (auto* stack = m_hostElement->keyframeEffectStack(pseudoId()))
</span><span class="cx">             return stack->requiresPseudoElement();
</span></span></pre></div>
<a id="trunkSourceWebCoredomPseudoElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/PseudoElement.h (269812 => 269813)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -41,7 +41,6 @@
</span><span class="cx">     void clearHostElement();
</span><span class="cx"> 
</span><span class="cx">     bool rendererIsNeeded(const RenderStyle&) override;
</span><del>-    bool isTargetedByKeyframeEffectRequiringPseudoElement();
</del><span class="cx"> 
</span><span class="cx">     bool canStartSelection() const override { return false; }
</span><span class="cx">     bool canContainRangeEndPoint() const override { return false; }
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingupdatingRenderTreeUpdatercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.cpp (269812 => 269813)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -191,7 +191,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (elementUpdates)
</span><del>-            updateElementRenderer(element, elementUpdates->update);
</del><ins>+            updateElementRenderer(element, *elementUpdates);
</ins><span class="cx"> 
</span><span class="cx">         storePreviousRenderer(element);
</span><span class="cx"> 
</span><span class="lines">@@ -251,13 +251,13 @@
</span><span class="cx"> void RenderTreeUpdater::updateBeforeDescendants(Element& element, const Style::ElementUpdates* updates)
</span><span class="cx"> {
</span><span class="cx">     if (updates)
</span><del>-        generatedContent().updatePseudoElement(element, updates->beforePseudoElementUpdate, PseudoId::Before);
</del><ins>+        generatedContent().updatePseudoElement(element, *updates, PseudoId::Before);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RenderTreeUpdater::updateAfterDescendants(Element& element, const Style::ElementUpdates* updates)
</span><span class="cx"> {
</span><span class="cx">     if (updates)
</span><del>-        generatedContent().updatePseudoElement(element, updates->afterPseudoElementUpdate, PseudoId::After);
</del><ins>+        generatedContent().updatePseudoElement(element, *updates, PseudoId::After);
</ins><span class="cx"> 
</span><span class="cx">     auto* renderer = element.renderer();
</span><span class="cx">     if (!renderer)
</span><span class="lines">@@ -297,13 +297,23 @@
</span><span class="cx">     m_builder.normalizeTreeAfterStyleChange(renderer, oldStyle);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void RenderTreeUpdater::updateElementRenderer(Element& element, const Style::ElementUpdate& update)
</del><ins>+void RenderTreeUpdater::updateElementRenderer(Element& element, const Style::ElementUpdates& updates)
</ins><span class="cx"> {
</span><span class="cx"> #if PLATFORM(IOS_FAMILY)
</span><span class="cx">     ContentChangeObserver::StyleChangeScope observingScope(m_document, element);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    bool shouldTearDownRenderers = update.change == Style::Change::Renderer && (element.renderer() || element.hasDisplayContents());
</del><ins>+    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());
</ins><span class="cx">     if (shouldTearDownRenderers) {
</span><span class="cx">         if (!element.renderer()) {
</span><span class="cx">             // We may be tearing down a descendant renderer cached in renderTreePosition.
</span><span class="lines">@@ -311,15 +321,15 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // display:none cancels animations.
</span><del>-        auto teardownType = update.style->display() == DisplayType::None ? TeardownType::RendererUpdateCancelingAnimations : TeardownType::RendererUpdate;
</del><ins>+        auto teardownType = elementUpdate.style->display() == DisplayType::None ? TeardownType::RendererUpdateCancelingAnimations : TeardownType::RendererUpdate;
</ins><span class="cx">         tearDownRenderers(element, teardownType, m_builder);
</span><span class="cx"> 
</span><span class="cx">         renderingParent().didCreateOrDestroyChildRenderer = true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool hasDisplayContents = update.style->display() == DisplayType::Contents;
</del><ins>+    bool hasDisplayContents = elementUpdate.style->display() == DisplayType::Contents;
</ins><span class="cx">     if (hasDisplayContents)
</span><del>-        element.storeDisplayContentsStyle(RenderStyle::clonePtr(*update.style));
</del><ins>+        element.storeDisplayContentsStyle(WTFMove(elementUpdateStyle));
</ins><span class="cx">     else
</span><span class="cx">         element.resetComputedStyle();
</span><span class="cx"> 
</span><span class="lines">@@ -327,7 +337,7 @@
</span><span class="cx">     if (shouldCreateNewRenderer) {
</span><span class="cx">         if (element.hasCustomStyleResolveCallbacks())
</span><span class="cx">             element.willAttachRenderers();
</span><del>-        createRenderer(element, RenderStyle::clone(*update.style));
</del><ins>+        createRenderer(element, WTFMove(*elementUpdateStyle));
</ins><span class="cx"> 
</span><span class="cx">         renderingParent().didCreateOrDestroyChildRenderer = true;
</span><span class="cx">         return;
</span><span class="lines">@@ -337,20 +347,20 @@
</span><span class="cx">         return;
</span><span class="cx">     auto& renderer = *element.renderer();
</span><span class="cx"> 
</span><del>-    if (update.recompositeLayer) {
-        updateRendererStyle(renderer, RenderStyle::clone(*update.style), StyleDifference::RecompositeLayer);
</del><ins>+    if (elementUpdate.recompositeLayer) {
+        updateRendererStyle(renderer, WTFMove(*elementUpdateStyle), StyleDifference::RecompositeLayer);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (update.change == Style::Change::None) {
-        if (pseudoStyleCacheIsInvalid(&renderer, update.style.get())) {
-            updateRendererStyle(renderer, RenderStyle::clone(*update.style), StyleDifference::Equal);
</del><ins>+    if (elementUpdate.change == Style::Change::None) {
+        if (pseudoStyleCacheIsInvalid(&renderer, elementUpdateStyle.get())) {
+            updateRendererStyle(renderer, WTFMove(*elementUpdateStyle), StyleDifference::Equal);
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    updateRendererStyle(renderer, RenderStyle::clone(*update.style), StyleDifference::Equal);
</del><ins>+    updateRendererStyle(renderer, WTFMove(*elementUpdateStyle), StyleDifference::Equal);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RenderTreeUpdater::createRenderer(Element& element, RenderStyle&& style)
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingupdatingRenderTreeUpdaterh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.h (269812 => 269813)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -58,7 +58,7 @@
</span><span class="cx">     void updateRenderTree(ContainerNode& root);
</span><span class="cx">     void updateTextRenderer(Text&, const Style::TextUpdate*);
</span><span class="cx">     void createTextRenderer(Text&, const Style::TextUpdate*);
</span><del>-    void updateElementRenderer(Element&, const Style::ElementUpdate&);
</del><ins>+    void updateElementRenderer(Element&, const Style::ElementUpdates&);
</ins><span class="cx">     void updateRendererStyle(RenderElement&, RenderStyle&&, StyleDifference);
</span><span class="cx">     void createRenderer(Element&, RenderStyle&&);
</span><span class="cx">     void updateBeforeDescendants(Element&, const Style::ElementUpdates*);
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingupdatingRenderTreeUpdaterGeneratedContentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/updating/RenderTreeUpdaterGeneratedContent.cpp (269812 => 269813)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -69,8 +69,21 @@
</span><span class="cx">     ASSERT(!lastQuote);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void createContentRenderers(RenderTreeBuilder& builder, RenderElement& pseudoRenderer, const RenderStyle& style)
</del><ins>+static bool elementIsTargetedByKeyframeEffectRequiringPseudoElement(const Element* element, PseudoId pseudoId)
</ins><span class="cx"> {
</span><ins>+    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)
+{
</ins><span class="cx">     if (auto* contentData = style.contentData()) {
</span><span class="cx">         for (const ContentData* content = contentData; content; content = content->next()) {
</span><span class="cx">             auto child = content->createContentRenderer(pseudoRenderer.document(), style);
</span><span class="lines">@@ -80,7 +93,7 @@
</span><span class="cx">     } else {
</span><span class="cx">         // The only valid scenario where this method is called without the "content" property being set
</span><span class="cx">         // is the case where a pseudo-element has animations set on it via the Web Animations API.
</span><del>-        ASSERT(is<PseudoElement>(pseudoRenderer.element()) && downcast<PseudoElement>(*pseudoRenderer.element()).isTargetedByKeyframeEffectRequiringPseudoElement());
</del><ins>+        ASSERT_UNUSED(pseudoId, elementIsTargetedByKeyframeEffectRequiringPseudoElement(pseudoRenderer.element(), pseudoId));
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -94,7 +107,7 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void RenderTreeUpdater::GeneratedContent::updatePseudoElement(Element& current, const Optional<Style::ElementUpdate>& update, PseudoId pseudoId)
</del><ins>+void RenderTreeUpdater::GeneratedContent::updatePseudoElement(Element& current, const Style::ElementUpdates& updates, PseudoId pseudoId)
</ins><span class="cx"> {
</span><span class="cx">     PseudoElement* pseudoElement = pseudoId == PseudoId::Before ? current.beforePseudoElement() : current.afterPseudoElement();
</span><span class="cx"> 
</span><span class="lines">@@ -101,7 +114,14 @@
</span><span class="cx">     if (auto* renderer = pseudoElement ? pseudoElement->renderer() : nullptr)
</span><span class="cx">         m_updater.renderTreePosition().invalidateNextSibling(*renderer);
</span><span class="cx"> 
</span><del>-    if (!needsPseudoElement(update) && (!pseudoElement || !pseudoElement->isTargetedByKeyframeEffectRequiringPseudoElement())) {
</del><ins>+    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))) {
</ins><span class="cx">         if (pseudoElement) {
</span><span class="cx">             if (pseudoId == PseudoId::Before)
</span><span class="cx">                 removeBeforePseudoElement(current, m_updater.m_builder);
</span><span class="lines">@@ -111,7 +131,7 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (update->change == Style::Change::None)
</del><ins>+    if (!update || update->change == Style::Change::None)
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     pseudoElement = &current.ensurePseudoElement(pseudoId);
</span><span class="lines">@@ -125,10 +145,14 @@
</span><span class="cx">         contentsStyle->copyContentFrom(*update->style);
</span><span class="cx"> 
</span><span class="cx">         Style::ElementUpdate contentsUpdate { WTFMove(contentsStyle), update->change, update->recompositeLayer };
</span><del>-        m_updater.updateElementRenderer(*pseudoElement, contentsUpdate);
</del><ins>+        Style::ElementUpdates contentsUpdates { WTFMove(contentsUpdate), Style::DescendantsToResolve::None, { } };
+        m_updater.updateElementRenderer(*pseudoElement, WTFMove(contentsUpdates));
</ins><span class="cx">         pseudoElement->storeDisplayContentsStyle(RenderStyle::clonePtr(*update->style));
</span><span class="cx">     } else {
</span><del>-        m_updater.updateElementRenderer(*pseudoElement, *update);
</del><ins>+        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));
</ins><span class="cx">         ASSERT(!pseudoElement->hasDisplayContents());
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -137,7 +161,7 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     if (update->change == Style::Change::Renderer)
</span><del>-        createContentRenderers(m_updater.m_builder, *pseudoElementRenderer, *update->style);
</del><ins>+        createContentRenderers(m_updater.m_builder, *pseudoElementRenderer, *update->style, pseudoId);
</ins><span class="cx">     else
</span><span class="cx">         updateStyleForContentRenderers(*pseudoElementRenderer, *update->style);
</span><span class="cx"> 
</span><span class="lines">@@ -148,7 +172,7 @@
</span><span class="cx">     m_updater.m_builder.updateAfterDescendants(*pseudoElementRenderer);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool RenderTreeUpdater::GeneratedContent::needsPseudoElement(const Optional<Style::ElementUpdate>& update)
</del><ins>+bool RenderTreeUpdater::GeneratedContent::needsPseudoElement(const Style::ElementUpdate* update)
</ins><span class="cx"> {
</span><span class="cx">     if (!update)
</span><span class="cx">         return false;
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingupdatingRenderTreeUpdaterGeneratedContenth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/updating/RenderTreeUpdaterGeneratedContent.h (269812 => 269813)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -38,7 +38,7 @@
</span><span class="cx"> public:
</span><span class="cx">     GeneratedContent(RenderTreeUpdater&);
</span><span class="cx"> 
</span><del>-    void updatePseudoElement(Element&, const Optional<Style::ElementUpdate>&, PseudoId);
</del><ins>+    void updatePseudoElement(Element&, const Style::ElementUpdates&, PseudoId);
</ins><span class="cx">     void updateRemainingQuotes();
</span><span class="cx"> 
</span><span class="cx">     static void removeBeforePseudoElement(Element&, RenderTreeBuilder&);
</span><span class="lines">@@ -47,7 +47,7 @@
</span><span class="cx"> private:
</span><span class="cx">     void updateQuotesUpTo(RenderQuote*);
</span><span class="cx">     
</span><del>-    bool needsPseudoElement(const Optional<Style::ElementUpdate>&);
</del><ins>+    bool needsPseudoElement(const Style::ElementUpdate*);
</ins><span class="cx"> 
</span><span class="cx">     RenderTreeUpdater& m_updater;
</span><span class="cx">     WeakPtr<RenderQuote> m_previousUpdatedQuote;
</span></span></pre></div>
<a id="trunkSourceWebCorestyleStyleTreeResolvercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/style/StyleTreeResolver.cpp (269812 => 269813)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -54,6 +54,7 @@
</span><span class="cx"> #include "StyleScope.h"
</span><span class="cx"> #include "Text.h"
</span><span class="cx"> #include "WebAnimationTypes.h"
</span><ins>+#include "WebAnimationUtilities.h"
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="lines">@@ -244,8 +245,11 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    auto beforeUpdate = resolvePseudoStyle(element, update, PseudoId::Before);
-    auto afterUpdate = resolvePseudoStyle(element, update, PseudoId::After);
</del><ins>+    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));
+    }
</ins><span class="cx"> 
</span><span class="cx"> #if ENABLE(TOUCH_ACTION_REGIONS)
</span><span class="cx">     // FIXME: Track this exactly.
</span><span class="lines">@@ -257,11 +261,13 @@
</span><span class="cx">         m_document.setMayHaveEditableElements();
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    return { WTFMove(update), descendantsToResolve, WTFMove(beforeUpdate), WTFMove(afterUpdate) };
</del><ins>+    return { WTFMove(update), descendantsToResolve, WTFMove(pseudoUpdates) };
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-ElementUpdate TreeResolver::resolvePseudoStyle(Element& element, const ElementUpdate& elementUpdate, PseudoId pseudoId)
</del><ins>+Optional<ElementUpdate> TreeResolver::resolvePseudoStyle(Element& element, const ElementUpdate& elementUpdate, PseudoId pseudoId)
</ins><span class="cx"> {
</span><ins>+    if (pseudoId == PseudoId::Marker && elementUpdate.style->display() != DisplayType::ListItem)
+        return { };
</ins><span class="cx">     if (elementUpdate.style->display() == DisplayType::None)
</span><span class="cx">         return { };
</span><span class="cx">     if (!elementUpdate.style->hasPseudoStyle(pseudoId))
</span><span class="lines">@@ -271,8 +277,7 @@
</span><span class="cx">     if (!pseudoStyle)
</span><span class="cx">         return { };
</span><span class="cx"> 
</span><del>-    auto* pseudoElement = pseudoId == PseudoId::Before ? element.beforePseudoElement() : element.afterPseudoElement();
-    bool hasAnimations = pseudoElement && pseudoElement->isTargetedByKeyframeEffectRequiringPseudoElement();
</del><ins>+    bool hasAnimations = pseudoStyle->hasAnimationsOrTransitions() || element.hasKeyframeEffects(pseudoId);
</ins><span class="cx">     if (!pseudoElementRendererIsNeeded(pseudoStyle.get()) && !hasAnimations)
</span><span class="cx">         return { };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorestyleStyleTreeResolverh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/style/StyleTreeResolver.h (269812 => 269813)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -62,7 +62,7 @@
</span><span class="cx">     ElementUpdates resolveElement(Element&);
</span><span class="cx"> 
</span><span class="cx">     ElementUpdate createAnimatedElementUpdate(std::unique_ptr<RenderStyle>, const Styleable&, Change);
</span><del>-    ElementUpdate resolvePseudoStyle(Element&, const ElementUpdate&, PseudoId);
</del><ins>+    Optional<ElementUpdate> resolvePseudoStyle(Element&, const ElementUpdate&, PseudoId);
</ins><span class="cx"> 
</span><span class="cx">     struct Scope : RefCounted<Scope> {
</span><span class="cx">         WTF_MAKE_STRUCT_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(TreeResolverScope);
</span></span></pre></div>
<a id="trunkSourceWebCorestyleStyleUpdateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/style/StyleUpdate.h (269812 => 269813)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -50,11 +50,12 @@
</span><span class="cx"> 
</span><span class="cx"> enum class DescendantsToResolve { None, ChildrenWithExplicitInherit, Children, All };
</span><span class="cx"> 
</span><ins>+using PseudoIdToElementUpdateMap = HashMap<PseudoId, ElementUpdate, WTF::IntHash<PseudoId>, WTF::StrongEnumHashTraits<PseudoId>>;
+
</ins><span class="cx"> struct ElementUpdates {
</span><span class="cx">     ElementUpdate update;
</span><span class="cx">     DescendantsToResolve descendantsToResolve { DescendantsToResolve::None };
</span><del>-    Optional<ElementUpdate> beforePseudoElementUpdate;
-    Optional<ElementUpdate> afterPseudoElementUpdate;
</del><ins>+    PseudoIdToElementUpdateMap pseudoElementUpdates;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> struct TextUpdate {
</span></span></pre>
</div>
</div>

</body>
</html>