Merge mozilla-central to inbound. a=merge CLOSED TREE
authorBogdan Tara <btara@mozilla.com>
Mon, 09 Jul 2018 13:08:22 +0300
changeset 815593 7f6bdd8d1074ebefb3ffe377bd24285848484eae
parent 815587 3c102477c730ffe75c784c5e2086d77fedeaf027 (current diff)
parent 815592 3d20b0701781731e0f9b08e1cd40ac842f385e03 (diff)
child 815594 4ff5720cadae8374a02409f63364b46984370865
push id115563
push userbmo:ntim.bugs@gmail.com
push dateMon, 09 Jul 2018 12:45:57 +0000
reviewersmerge
milestone63.0a1
Merge mozilla-central to inbound. a=merge CLOSED TREE
--- a/devtools/client/inspector/animation/test/browser.ini
+++ b/devtools/client/inspector/animation/test/browser.ini
@@ -59,16 +59,17 @@ skip-if = (verify && !debug)
 [browser_animation_keyframes-progress-bar_after-resuming.js]
 [browser_animation_logic_adjust-time.js]
 [browser_animation_logic_adjust-time-with-playback-rate.js]
 [browser_animation_logic_auto-stop.js]
 [browser_animation_logic_avoid-updating-during-hiding.js]
 [browser_animation_logic_created-time.js]
 [browser_animation_logic_mutations.js]
 [browser_animation_logic_mutations_fast.js]
+[browser_animation_logic_mutations_properties.js]
 [browser_animation_logic_scroll-amount.js]
 [browser_animation_pause-resume-button.js]
 [browser_animation_pause-resume-button_end-time.js]
 [browser_animation_pause-resume-button_respectively.js]
 [browser_animation_pause-resume-button_spacebar.js]
 [browser_animation_playback-rate-selector.js]
 [browser_animation_pseudo-element.js]
 [browser_animation_rewind-button.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/animation/test/browser_animation_logic_mutations_properties.js
@@ -0,0 +1,81 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test whether animation was changed after altering following properties.
+// * delay
+// * direction
+// * duration
+// * easing (animationTimingFunction in case of CSS Animationns)
+// * fill
+// * iterations
+// * endDelay (script animation only)
+// * iterationStart (script animation only)
+// * playbackRate (script animation only)
+
+const SEC = 1000;
+const TEST_EFFECT_TIMING = {
+  delay: 20 * SEC,
+  direction: "reverse",
+  duration: 20 * SEC,
+  easing: "steps(1)",
+  endDelay: 20 * SEC,
+  fill: "backwards",
+  iterations: 20,
+  iterationStart: 20 * SEC,
+};
+const TEST_PLAYBACK_RATE = 0.1;
+
+add_task(async function() {
+  await addTab(URL_ROOT + "doc_simple_animation.html");
+  await removeAnimatedElementsExcept([".animated", ".end-delay"]);
+  const { animationInspector } = await openAnimationInspector();
+  await setCSSAnimationProperties(animationInspector);
+  assertProperties(animationInspector.state.animations[0], false);
+  await setScriptAnimationProperties(animationInspector);
+  assertProperties(animationInspector.state.animations[1], true);
+});
+
+async function setCSSAnimationProperties(animationInspector) {
+  const properties = {
+    animationDelay: `${ TEST_EFFECT_TIMING.delay }ms`,
+    animationDirection: TEST_EFFECT_TIMING.direction,
+    animationDuration: `${ TEST_EFFECT_TIMING.duration }ms`,
+    animationFillMode: TEST_EFFECT_TIMING.fill,
+    animationIterationCount: TEST_EFFECT_TIMING.iterations,
+    animationTimingFunction: TEST_EFFECT_TIMING.easing,
+  };
+
+  await setStyles(animationInspector, ".animated", properties);
+}
+
+async function setScriptAnimationProperties(animationInspector) {
+  await setEffectTimingAndPlayback(animationInspector, ".end-delay",
+                                   TEST_EFFECT_TIMING, TEST_PLAYBACK_RATE);
+}
+
+function assertProperties(animation, isScriptAnimation) {
+  is(animation.state.delay, TEST_EFFECT_TIMING.delay,
+     `Delay should be ${ TEST_EFFECT_TIMING.delay }`);
+  is(animation.state.direction, TEST_EFFECT_TIMING.direction,
+     `Direction should be ${ TEST_EFFECT_TIMING.direction }`);
+  is(animation.state.duration, TEST_EFFECT_TIMING.duration,
+     `Duration should be ${ TEST_EFFECT_TIMING.duration }`);
+  is(animation.state.fill, TEST_EFFECT_TIMING.fill,
+     `Fill should be ${ TEST_EFFECT_TIMING.fill }`);
+  is(animation.state.iterationCount, TEST_EFFECT_TIMING.iterations,
+     `Iterations should be ${ TEST_EFFECT_TIMING.iterations }`);
+
+  if (isScriptAnimation) {
+    is(animation.state.easing, TEST_EFFECT_TIMING.easing,
+       `Easing should be ${ TEST_EFFECT_TIMING.easing }`);
+    is(animation.state.iterationStart, TEST_EFFECT_TIMING.iterationStart,
+       `IterationStart should be ${ TEST_EFFECT_TIMING.iterationStart }`);
+    is(animation.state.playbackRate, TEST_PLAYBACK_RATE,
+       `PlaybackRate should be ${ TEST_PLAYBACK_RATE }`);
+  } else {
+    is(animation.state.animationTimingFunction, TEST_EFFECT_TIMING.easing,
+       `AnimationTimingFunction should be ${ TEST_EFFECT_TIMING.easing }`);
+  }
+}
--- a/devtools/client/inspector/animation/test/doc_frame_script.js
+++ b/devtools/client/inspector/animation/test/doc_frame_script.js
@@ -13,16 +13,37 @@ addMessageListener("Test:RemoveAnimatedE
     if (isRemovableElement(animation, selectors)) {
       animation.effect.target.remove();
     }
   }
 
   sendAsyncMessage("Test:RemoveAnimatedElementsExcept");
 });
 
+addMessageListener("Test:SetEffectTimingAndPlayback", function(msg) {
+  const { effectTiming, playbackRate, selector } = msg.data;
+  let selectedAnimation = null;
+
+  for (const animation of content.document.getAnimations()) {
+    if (animation.effect.target.matches(selector)) {
+      selectedAnimation = animation;
+      break;
+    }
+  }
+
+  if (!selectedAnimation) {
+    return;
+  }
+
+  selectedAnimation.playbackRate = playbackRate;
+  selectedAnimation.effect.updateTiming(effectTiming);
+
+  sendAsyncMessage("Test:SetEffectTimingAndPlayback");
+});
+
 function isRemovableElement(animation, selectors) {
   for (const selector of selectors) {
     if (animation.effect.target.matches(selector)) {
       return false;
     }
   }
 
   return true;
--- a/devtools/client/inspector/animation/test/head.js
+++ b/devtools/client/inspector/animation/test/head.js
@@ -473,16 +473,38 @@ const setClassAttribute = async function
     attributeValue: cls,
     selector,
   };
   await executeInContent("devtools:test:setAttribute", options);
   await waitForSummaryAndDetail(animationInspector);
 };
 
 /**
+ * Set a new style properties to the node for the given selector.
+ *
+ * @param {AnimationInspector} animationInspector
+ * @param {String} selector
+ * @param {Object} properties
+ *        e.g. {
+ *               animationDuration: "1000ms",
+ *               animationTimingFunction: "linear",
+ *             }
+ */
+const setEffectTimingAndPlayback = async function(animationInspector,
+                                                  selector, effectTiming, playbackRate) {
+  const options = {
+    effectTiming,
+    playbackRate,
+    selector,
+  };
+  await executeInContent("Test:SetEffectTimingAndPlayback", options);
+  await waitForSummaryAndDetail(animationInspector);
+};
+
+/**
  * Set the sidebar width by given parameter.
  *
  * @param {String} width
  *        Change sidebar width by given parameter.
  * @param {InspectorPanel} inspector
  *        The instance of InspectorPanel currently loaded in the toolbox
  * @return {Promise} Resolves when the sidebar size changed.
  */
@@ -509,16 +531,36 @@ const setStyle = async function(animatio
     propertyValue,
     selector,
   };
   await executeInContent("devtools:test:setStyle", options);
   await waitForSummaryAndDetail(animationInspector);
 };
 
 /**
+ * Set a new style properties to the node for the given selector.
+ *
+ * @param {AnimationInspector} animationInspector
+ * @param {String} selector
+ * @param {Object} properties
+ *        e.g. {
+ *               animationDuration: "1000ms",
+ *               animationTimingFunction: "linear",
+ *             }
+ */
+const setStyles = async function(animationInspector, selector, properties) {
+  const options = {
+    properties,
+    selector,
+  };
+  await executeInContent("devtools:test:setMultipleStyles", options);
+  await waitForSummaryAndDetail(animationInspector);
+};
+
+/**
  * Wait for rendering.
  *
  * @param {AnimationInspector} animationInspector
  */
 const waitForRendering = async function(animationInspector) {
   await Promise.all([
     waitForAllAnimationTargets(animationInspector),
     waitForAllSummaryGraph(animationInspector),
--- a/devtools/client/shared/test/frame-script-utils.js
+++ b/devtools/client/shared/test/frame-script-utils.js
@@ -149,16 +149,43 @@ addMessageListener("devtools:test:setSty
   }
 
   node.style[propertyName] = propertyValue;
 
   sendAsyncMessage("devtools:test:setStyle");
 });
 
 /**
+ * Set multiple styles to the node for the given selector at once.
+ * @param {Object} data
+ * - {String} selector The CSS selector to get the node (can be a "super"
+ *   selector).
+ * - {Object} properties
+ *            e.g. {
+ *              opacity: 0,
+ *              color: "red",
+ *              animationTimingFunction: "linear",
+ *            }
+ */
+addMessageListener("devtools:test:setMultipleStyles", function(msg) {
+  const {selector, properties} = msg.data;
+  const node = superQuerySelector(selector);
+  if (!node) {
+    return;
+  }
+
+  for (const propertyName in properties) {
+    const propertyValue = properties[propertyName];
+    node.style[propertyName] = propertyValue;
+  }
+
+  sendAsyncMessage("devtools:test:setMultipleStyles");
+});
+
+/**
  * Set a given attribute value on a node.
  * @param {Object} data
  * - {String} selector The CSS selector to get the node (can be a "super"
  *   selector).
  * - {String} attributeName The name of the attribute to set.
  * - {String} attributeValue The value for the attribute.
  */
 addMessageListener("devtools:test:setAttribute", function(msg) {
--- a/devtools/server/actors/animation.js
+++ b/devtools/server/actors/animation.js
@@ -384,26 +384,30 @@ var AnimationPlayerActor = protocol.Acto
       if (hasCurrentAnimation(removedAnimations)) {
         // Reset the local copy of the state on removal, since the animation can
         // be kept on the client and re-added, its state needs to be sent in
         // full.
         this.currentState = null;
       }
 
       if (hasCurrentAnimation(changedAnimations)) {
-        // Only consider the state has having changed if any of delay, duration,
-        // iterationCount, iterationStart, or playbackRate has changed (for now
-        // at least).
+        // Only consider the state has having changed if any of effect timing properties,
+        // animationTimingFunction or playbackRate has changed.
         const newState = this.getState();
         const oldState = this.currentState;
         hasChanged = newState.delay !== oldState.delay ||
                      newState.iterationCount !== oldState.iterationCount ||
                      newState.iterationStart !== oldState.iterationStart ||
                      newState.duration !== oldState.duration ||
                      newState.endDelay !== oldState.endDelay ||
+                     newState.direction !== oldState.direction ||
+                     newState.easing !== oldState.easing ||
+                     newState.fill !== oldState.fill ||
+                     newState.animationTimingFunction !==
+                       oldState.animationTimingFunction ||
                      newState.playbackRate !== oldState.playbackRate;
         break;
       }
     }
 
     if (hasChanged) {
       this.emit("changed", this.getCurrentState());
     }
new file mode 100644
--- /dev/null
+++ b/layout/base/crashtests/1458121.html
@@ -0,0 +1,23 @@
+<script>
+window.requestIdleCallback(function(){
+  document.documentElement.style.display="none";
+  document.documentElement.getBoundingClientRect();
+  document.documentElement.style.display="";
+});
+</script>
+<style>
+body {
+  -webkit-border-radius: 16px;
+  overflow-x: hidden;
+  -webkit-filter: blur(0px);
+  width: 1em;
+}
+:root {
+  scroll-snap-destination: left top 36%;
+}
+#a {
+  overflow: scroll;
+  clip-path: url(#x);
+}
+</style>
+<dl id="a">|<dialog open>
--- a/layout/base/crashtests/crashtests.list
+++ b/layout/base/crashtests/crashtests.list
@@ -533,16 +533,17 @@ load 1437155.html
 pref(dom.webcomponents.shadowdom.enabled,true) load 1439016.html
 load 1442506.html
 load 1443027-1.html
 load 1448841-1.html
 load 1452839.html
 load 1453196.html
 load 1453342.html
 load 1453702.html
+load 1458121.html
 pref(dom.webcomponents.shadowdom.enabled,true) load 1461749.html
 load 1461812.html
 load 1462412.html
 load 1463940.html
 pref(dom.webcomponents.shadowdom.enabled,true) HTTP load 1464641.html
 load 1464737.html
 load 1467688.html
 load 1467964.html
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -9245,16 +9245,22 @@ bool nsDisplayMask::CanPaintOnMaskLayer(
   if (!nsSVGIntegrationUtils::IsMaskResourceReady(mFrame)) {
     return false;
   }
 
   if (gfxPrefs::DrawMaskLayer()) {
     return false;
   }
 
+  // We don't currently support this item creating a mask
+  // for both the clip-path, and rounded rect clipping.
+  if (GetClip().GetRoundedRectCount() != 0) {
+    return false;
+  }
+
   return true;
 }
 
 bool nsDisplayMask::ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                       nsRegion* aVisibleRegion)
 {
   // Our children may be made translucent or arbitrarily deformed so we should
   // not allow them to subtract area from aVisibleRegion.