Bug 1384120 - Replace old pseudo style context with a new style context including animations. r?emilio draft
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Tue, 08 Aug 2017 11:35:23 +0900
changeset 642400 c1d471ac352b231e76e387443bb293eb9628e3b6
parent 642399 87b6d99a490bfe892b84883e391ea3a5d35a38ab
child 724975 a1ac4377e6e61ca1c352fd9c793b9dc6ccbd1b02
push id72726
push userhikezoe@mozilla.com
push dateTue, 08 Aug 2017 04:14:27 +0000
reviewersemilio
bugs1384120
milestone57.0a1
Bug 1384120 - Replace old pseudo style context with a new style context including animations. r?emilio When a reframe happens on the parent of a pseudo element which has animations, we need to grab style for the pseudo element that includes the animations' style and also *replace* old style context (that does not include animations' style) with it. Otherwise, we will use the old style context that has *no* animations style, as a result, we will see a flicker right after the reframe. Two reftests in this patch fail without this fix. One is for CSS transitions, the other one is for CSS animations. MozReview-Commit-ID: 6pCdnQ1DGUY
layout/base/nsCSSFrameConstructor.cpp
layout/reftests/css-animations/reframe-and-animation-starts-at-the-same-time-ref.html
layout/reftests/css-animations/reframe-and-animation-starts-at-the-same-time.html
layout/reftests/css-animations/reftest.list
layout/reftests/css-transitions/reframe-and-transition-starts-at-the-same-time-ref.html
layout/reftests/css-transitions/reframe-and-transition-starts-at-the-same-time.html
layout/reftests/css-transitions/reftest.list
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1978,18 +1978,22 @@ nsCSSFrameConstructor::CreateGeneratedCo
       }
     }
   }
 
   // We may need to do a synchronous servo traversal in various uncommon cases.
   if (servoStyle) {
     if (hasServoAnimations) {
       // If animations are involved, we avoid the SetExplicitStyle optimization
-      // above.
+      // above. We need to grab style with animations from the pseudo element
+      // and replace old one.
       mPresShell->StyleSet()->AsServo()->StyleNewSubtree(container);
+      pseudoStyleContext =
+        styleSet->AsServo()->ResolveServoStyle(container,
+                                               ServoTraversalFlags::Empty);
     } else if (createdChildElement) {
       // If we created any children elements, Servo needs to traverse them, but
       // the root is already set up.
       mPresShell->StyleSet()->AsServo()->StyleNewChildren(container);
     }
   }
 
   AddFrameConstructionItemsInternal(aState, container, aParentFrame, elemName,
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-animations/reframe-and-animation-starts-at-the-same-time-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<style>
+#target::before {
+  content: '';
+  background-color: rgb(255, 255, 255);
+  height: 100px;
+  width: 100px;
+  position: absolute;
+}
+</style>
+<div id="target"></div>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-animations/reframe-and-animation-starts-at-the-same-time.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<style>
+@keyframes anim {
+  from { background-color: rgb(255, 255, 255); }
+  to { background-color: rgb(255, 255, 255); }
+}
+#target::before {
+  content: 'initial';
+  background-color: rgb(0, 0, 0);
+  height: 100px;
+  width: 100px;
+  position: absolute;
+}
+#target.hover::before{
+  content: '';
+  animation: anim 100s steps(1, start);
+}
+</style>
+<div id="target"></div>
+<script>
+window.addEventListener("load", () => {
+  target.className = 'hover';
+  target.addEventListener('animationstart', () => {
+    document.documentElement.classList.remove('reftest-wait');
+  });
+});
+</script>
+</html>
--- a/layout/reftests/css-animations/reftest.list
+++ b/layout/reftests/css-animations/reftest.list
@@ -49,8 +49,9 @@ fails == background-position-important.h
 == mask-size-after-finish-1a.html mask-anim-ref.html
 == mask-size-after-finish-1b.html mask-anim-ref.html
 == mask-size-in-delay-1a.html mask-anim-ref.html
 == mask-size-in-delay-1b.html mask-anim-ref.html
 
 == stop-animation-on-discarded-pseudo-element.html about:blank
 
 == updating-animation-on-pseudo-element.html updating-animation-on-pseudo-element-ref.html
+== reframe-and-animation-starts-at-the-same-time.html reframe-and-animation-starts-at-the-same-time-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-transitions/reframe-and-transition-starts-at-the-same-time-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<style>
+#target::before {
+  content: '';
+  background-color: rgb(255, 255, 255);
+  height: 100px;
+  width: 100px;
+  position: absolute;
+}
+</style>
+<div id="target"></div>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-transitions/reframe-and-transition-starts-at-the-same-time.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<style>
+#target::before {
+  transition: background-color 100s steps(1, end);
+  content: 'initial';
+  background-color: rgb(255, 255, 255);
+  height: 100px;
+  width: 100px;
+  position: absolute;
+}
+#target.hover::before{
+  background-color: rgb(0, 0, 0);
+  content: '';
+}
+</style>
+<div id="target"></div>
+<script>
+window.addEventListener("load", () => {
+  target.className = 'hover';
+  target.addEventListener('transitionstart', () => {
+    document.documentElement.classList.remove('reftest-wait');
+  });
+});
+</script>
+</html>
--- a/layout/reftests/css-transitions/reftest.list
+++ b/layout/reftests/css-transitions/reftest.list
@@ -2,9 +2,10 @@
 == transitions-inline-already-wrapped-2.html transitions-inline-ref.html
 == transitions-inline-rewrap-1.html transitions-inline-ref.html
 == transitions-inline-rewrap-2.html transitions-inline-ref.html
 == stacking-context-opacity-lose-to-animation.html stacking-context-transition-ref.html
 == stacking-context-transform-lose-to-animation.html stacking-context-transition-ref.html
 == stacking-context-opacity-wins-over-important-style.html stacking-context-transition-ref.html
 == stacking-context-transform-wins-over-important-style.html stacking-context-transition-ref.html
 == transition-and-animation-with-different-durations.html transition-and-animation-with-different-durations-ref.html
+== reframe-and-transition-starts-at-the-same-time.html reframe-and-transition-starts-at-the-same-time-ref.html
 == style-change-during-transition.html style-change-during-transition-ref.html