file_animation_api.html (4370B)
1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Test for Bug 1382545</title> 6 <script> 7 function waitForCondition(aCond, aCallback, aErrorMsg) { 8 var tries = 0; 9 var interval = setInterval(() => { 10 if (tries >= 30) { 11 opener.ok(false, aErrorMsg); 12 moveOn(); 13 return; 14 } 15 var conditionPassed; 16 try { 17 conditionPassed = aCond(); 18 } catch (e) { 19 opener.ok(false, `${e}\n${e.stack}`); 20 conditionPassed = false; 21 } 22 if (conditionPassed) { 23 moveOn(); 24 } 25 tries++; 26 }, 100); 27 var moveOn = () => { clearInterval(interval); aCallback(); }; 28 } 29 30 function runTest() { 31 let expectedPrecision = opener.expectedPrecision / 1000; 32 let isRounded = (x) => { 33 let rounded = (Math.floor(x / expectedPrecision) * expectedPrecision); 34 // First we do the perfectly normal check that should work just fine 35 if (rounded === x || x === 0) 36 return true; 37 38 // When we're diving by non-whole numbers, we may not get perfect 39 // multiplication/division because of floating points. 40 // When dealing with ms since epoch, a double's precision is on the order 41 // of 1/5 of a microsecond, so we use a value a little higher than that as 42 // our epsilon. 43 // To be clear, this error is introduced in our re-calculation of 'rounded' 44 // above in JavaScript. 45 if (Math.abs(rounded - x + expectedPrecision) < .0005) { 46 return true; 47 } else if (Math.abs(rounded - x) < .0005) { 48 return true; 49 } 50 51 // Then we handle the case where you're sub-millisecond and the timer is not 52 // We check that the timer is not sub-millisecond by assuming it is not if it 53 // returns an even number of milliseconds 54 if (expectedPrecision < 1 && Math.round(x) == x) { 55 if (Math.round(rounded) == x) { 56 return true; 57 } 58 } 59 60 // We are temporarily disabling this extra debugging failure because we expect to return false in some instances 61 // When we correct things we will re-enable it for debugging assistance 62 // opener.ok(false, "Looming Test Failure, Additional Debugging Info: Expected Precision: " + expectedPrecision + " Measured Value: " + x + 63 // " Rounded Vaue: " + rounded + " Fuzzy1: " + Math.abs(rounded - x + expectedPrecision) + 64 // " Fuzzy 2: " + Math.abs(rounded - x)); 65 66 return false; 67 }; 68 const testDiv = document.getElementById("testDiv"); 69 const animation = testDiv.animate({ opacity: [0, 1] }, 100000); 70 animation.play(); 71 72 waitForCondition( 73 () => animation.currentTime > 100, 74 () => { 75 // We have disabled Time Precision Reduction for CSS Animations, so we expect those tests to fail. 76 // If we are testing that preference, we accept either rounded or not rounded values as A-OK. 77 var maybeAcceptEverything = function(value) { 78 if (opener.prefName.includes("privacy.reduceTimerPrecision") && 79 !opener.prefName.includes("privacy.resistFingerprinting")) 80 return true; 81 return value; 82 }; 83 84 opener.ok(maybeAcceptEverything(isRounded(animation.startTime)), 85 "pref: " + opener.prefName + " - animation.startTime with precision " + expectedPrecision + " is not rounded: " + animation.startTime); 86 opener.ok(maybeAcceptEverything(isRounded(animation.currentTime)), 87 "pref: " + opener.prefName + " - animation.currentTime with precision " + expectedPrecision + " is not rounded: " + animation.currentTime); 88 opener.ok(maybeAcceptEverything(isRounded(animation.timeline.currentTime)), 89 "pref: " + opener.prefName + " - animation.timeline.currentTime with precision " + expectedPrecision + " is not rounded: " + animation.timeline.currentTime); 90 if (document.timeline) { 91 opener.ok(maybeAcceptEverything(isRounded(document.timeline.currentTime)), 92 "pref: " + opener.prefName + " - document.timeline.currentTime with precision " + expectedPrecision + " is not rounded: " + document.timeline.currentTime); 93 } 94 opener.done(); 95 window.close(); 96 }, 97 "animation failed to start"); 98 } 99 </script> 100 </head> 101 <body onload="runTest();"> 102 <div id="testDiv">test</div> 103 </body> 104 </html>