tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

file_domwindowutils_animation.html (7849B)


      1 <!DOCTYPE html>
      2 <html>
      3 <head>
      4  <meta charset="UTF-8">
      5  <title>DOMWindowUtils test with animation</title>
      6  <script src="/tests/SimpleTest/paint_listener.js"></script>
      7  <script src="/tests/dom/animation/test/testcommon.js"></script>
      8 </head>
      9 <body>
     10 <script type="application/javascript">
     11 
     12 const SimpleTest = window.opener.SimpleTest;
     13 const utils = SpecialPowers.getDOMWindowUtils(window);
     14 const next = window.opener.next;
     15 const is = window.opener.is;
     16 const ok = window.opener.ok;
     17 
     18 function addStyle(rules) {
     19  const extraStyle = document.createElement("style");
     20  document.head.appendChild(extraStyle);
     21  rules.forEach(rule => {
     22    extraStyle.sheet.insertRule(rule, extraStyle.sheet.cssRules.length);
     23  });
     24 }
     25 
     26 function deleteStyle() {
     27  document.head.querySelector("style").remove();
     28 }
     29 
     30 
     31 let propertyIndex = 0;
     32 
     33 function test_getUnanimatedComputedStyle() {
     34  const name = `--property-${++propertyIndex}`;
     35  CSS.registerProperty({
     36    name,
     37    syntax: "<length>",
     38    initialValue: "2px",
     39    inherits: false,
     40  });
     41  [
     42    {
     43      property: "opacity",
     44      keyframes: [1, 0],
     45      expectedInitialStyle: "1",
     46      expectedDuringTransitionStyle: "0",
     47      isDiscrete: false,
     48    },
     49    {
     50      property: name,
     51      keyframes: ["1px", "10px"],
     52      expectedInitialStyle: "2px",
     53      expectedDuringTransitionStyle: "2px",
     54      isDiscrete: true,
     55    },
     56    {
     57      property: "clear",
     58      keyframes: ["left", "inline-end"],
     59      expectedInitialStyle: "none",
     60      expectedDuringTransitionStyle: "inline-end",
     61      isDiscrete: true,
     62    },
     63  ].forEach(testcase => {
     64    const { property, keyframes, expectedInitialStyle,
     65            expectedDuringTransitionStyle, isDiscrete } = testcase;
     66 
     67    [null, "unset", "initial", "inherit"].forEach(initialStyle => {
     68      const scriptAnimation = target => {
     69        return target.animate({ [property]: keyframes }, 1000);
     70      }
     71      checkUnanimatedComputedStyle(property, initialStyle, null,
     72                                   expectedInitialStyle, expectedInitialStyle,
     73                                   scriptAnimation, "script animation");
     74 
     75      const cssAnimationStyle = `@keyframes cssanimation {`
     76                                + ` from { ${property}: ${ keyframes[0] }; }`
     77                                + ` to { ${property}: ${ keyframes[1] }; } }`;
     78      addStyle([cssAnimationStyle]);
     79      const cssAnimation = target => {
     80        target.style.animation = "cssanimation 1s";
     81        return target.getAnimations()[0];
     82      }
     83      checkUnanimatedComputedStyle(property, initialStyle, null,
     84                                   expectedInitialStyle, expectedInitialStyle,
     85                                   cssAnimation, "CSS Animations");
     86      deleteStyle();
     87 
     88      // We don't support discrete animations for CSS Transitions yet.
     89      // (bug 1320854)
     90      if (!isDiscrete) {
     91        const cssTransition = target => {
     92          target.style[property] = keyframes[0];
     93          target.style.transition =
     94            `${ property } 1s`;
     95          window.getComputedStyle(target)[property];
     96          target.style[property] = keyframes[1];
     97          return target.getAnimations()[0];
     98        }
     99        checkUnanimatedComputedStyle(property, initialStyle, null,
    100                                     expectedInitialStyle,
    101                                     expectedDuringTransitionStyle,
    102                                     cssTransition, "CSS Transitions");
    103      }
    104 
    105      addStyle([cssAnimationStyle,
    106                ".pseudo::before { content: '' }",
    107                ".animation::before { animation: cssanimation 1s }"]);
    108      const pseudoAnimation = target => {
    109        target.classList.add("animation");
    110        return target.getAnimations({ subtree: true })[0];
    111      }
    112      checkUnanimatedComputedStyle(property, initialStyle, "::before",
    113                                   expectedInitialStyle, expectedInitialStyle,
    114                                   pseudoAnimation, "Animation at pseudo");
    115      deleteStyle();
    116    });
    117  });
    118 
    119  const div = document.createElement("div");
    120  document.body.appendChild(div);
    121 
    122  SimpleTest.doesThrow(
    123    () => utils.getUnanimatedComputedStyle(div, null, "background", utils.FLUSH_NONE),
    124    "NS_ERROR_INVALID_ARG",
    125    "Shorthand property should throw");
    126 
    127  SimpleTest.doesThrow(
    128    () => utils.getUnanimatedComputedStyle(div, null, "invalid", utils.FLUSH_NONE),
    129    "NS_ERROR_INVALID_ARG",
    130    "Invalid property should throw");
    131 
    132  SimpleTest.doesThrow(
    133    () => utils.getUnanimatedComputedStyle(null, null, "opacity", utils.FLUSH_NONE),
    134    "NS_ERROR_INVALID_ARG",
    135    "Null element should throw");
    136 
    137  SimpleTest.doesThrow(
    138    () => utils.getUnanimatedComputedStyle(div, null, "opacity", utils.FLUSH_LAYOUT),
    139    "NS_ERROR_INVALID_ARG",
    140    "FLUSH_LAYOUT option should throw");
    141 
    142  SimpleTest.doesThrow(
    143    () => utils.getUnanimatedComputedStyle(div, "::before", "opacity", utils.FLUSH_NONE),
    144    "NS_ERROR_FAILURE",
    145    "Non-existent pseudo should throw");
    146 
    147  // Flush styles since getUnanimatedComputedStyle flushes pending styles even
    148  // with FLUSH_NONE option if the element hasn't yet styled.
    149  getComputedStyle(div).opacity;
    150 
    151  div.style.opacity = "0";
    152  is(utils.getUnanimatedComputedStyle(div, null, "opacity", utils.FLUSH_NONE),
    153     "1",
    154     "getUnanimatedComputedStyle with FLUSH_NONE should not flush pending styles");
    155 
    156  is(utils.getUnanimatedComputedStyle(div, null, "opacity", utils.FLUSH_STYLE),
    157     "0",
    158     "getUnanimatedComputedStyle with FLUSH_STYLE should flush pending styles");
    159 
    160  div.remove();
    161 
    162  test_needsFlushWithThrottledAnimations();
    163 }
    164 
    165 function checkUnanimatedComputedStyle(property, initialStyle, pseudoType,
    166                                      expectedBeforeAnimation,
    167                                      expectedDuringAnimation,
    168                                      animate, animationType) {
    169  const div = document.createElement("div");
    170  document.body.appendChild(div);
    171 
    172  if (initialStyle) {
    173    div.style[property] = initialStyle;
    174  }
    175  if (pseudoType) {
    176    div.classList.add("pseudo");
    177  }
    178 
    179  is(utils.getUnanimatedComputedStyle(div, pseudoType, property, utils.FLUSH_STYLE),
    180     expectedBeforeAnimation,
    181     `'${ property }' property with '${ initialStyle }' style `
    182     + `should be '${ expectedBeforeAnimation }' `
    183     + `before animating by ${ animationType }`);
    184 
    185  const animation = animate(div);
    186  animation.currentTime = 500;
    187  is(utils.getUnanimatedComputedStyle(div, pseudoType, property, utils.FLUSH_STYLE),
    188     expectedDuringAnimation,
    189     `'${ property }' property with '${ initialStyle }' style `
    190     + `should be '${ expectedDuringAnimation }' `
    191     + `even while animating by ${ animationType }`);
    192 
    193  div.remove();
    194 }
    195 
    196 function test_needsFlushWithThrottledAnimations() {
    197  const div = document.createElement("div");
    198  div.style = "width: 100px; height: 100px; background-color: blue;";
    199  document.body.appendChild(div);
    200 
    201  const animation = div.animate({ opacity: [ 0, 1 ] },
    202                                { duration: 100000, iterations: Infinity });
    203  waitForAnimationReadyToRestyle(animation).then(() => {
    204    ok(SpecialPowers.wrap(animation).isRunningOnCompositor,
    205        "Opacity animation should run on the compositor");
    206 
    207    // FIXME! Bug 1442861: We should make sure needsFlush() returns true
    208    // before flusing layout.
    209    //ok(utils.needsFlush(SpecialPowers.Ci.nsIDOMWindowUtils.FLUSH_STYLE),
    210    //   "needsFlush should return true if there is an animation on the compositor");
    211 
    212    // Flush layout.
    213    document.documentElement.getBoundingClientRect();
    214 
    215    ok(!utils.needsFlush(SpecialPowers.Ci.nsIDOMWindowUtils.FLUSH_STYLE),
    216        "needsFlush should return false after flushing layout");
    217 
    218    div.remove();
    219    next();
    220    window.close();
    221  });
    222 }
    223 
    224 window.addEventListener("load", test_getUnanimatedComputedStyle);
    225 
    226 </script>
    227 </body>
    228 </html>