undefined reference to 'JSC::B3::BasicBlock::fallThrough() const
[WebKit-https.git] / LayoutTests / imported / w3c / web-platform-tests / web-animations / testcommon.js
1 /*
2 Distributed under both the W3C Test Suite License [1] and the W3C
3 3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
4 policies and contribution forms [3].
5
6 [1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
7 [2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
8 [3] http://www.w3.org/2004/10/27-testcases
9  */
10
11 'use strict';
12
13 const MS_PER_SEC = 1000;
14
15 // The recommended minimum precision to use for time values[1].
16 //
17 // [1] https://drafts.csswg.org/web-animations/#precision-of-time-values
18 const TIME_PRECISION = 0.0005; // ms
19
20 // Allow implementations to substitute an alternative method for comparing
21 // times based on their precision requirements.
22 if (!window.assert_times_equal) {
23   window.assert_times_equal = (actual, expected, description) => {
24     assert_approx_equals(actual, expected, TIME_PRECISION * 2, description);
25   };
26 }
27
28 // Allow implementations to substitute an alternative method for comparing
29 // a time value based on its precision requirements with a fixed value.
30 if (!window.assert_time_equals_literal) {
31   window.assert_time_equals_literal = (actual, expected, description) => {
32     assert_approx_equals(actual, expected, TIME_PRECISION, description);
33   }
34 }
35
36 // creates div element, appends it to the document body and
37 // removes the created element during test cleanup
38 function createDiv(test, doc) {
39   return createElement(test, 'div', doc);
40 }
41
42 // creates element of given tagName, appends it to the document body and
43 // removes the created element during test cleanup
44 // if tagName is null or undefined, returns div element
45 function createElement(test, tagName, doc) {
46   if (!doc) {
47     doc = document;
48   }
49   const element = doc.createElement(tagName || 'div');
50   doc.body.appendChild(element);
51   test.add_cleanup(() => {
52     element.remove();
53   });
54   return element;
55 }
56
57 // Creates a style element with the specified rules, appends it to the document
58 // head and removes the created element during test cleanup.
59 // |rules| is an object. For example:
60 // { '@keyframes anim': '' ,
61 //   '.className': 'animation: anim 100s;' };
62 // or
63 // { '.className1::before': 'content: ""; width: 0px; transition: all 10s;',
64 //   '.className2::before': 'width: 100px;' };
65 // The object property name could be a keyframes name, or a selector.
66 // The object property value is declarations which are property:value pairs
67 // split by a space.
68 function createStyle(test, rules, doc) {
69   if (!doc) {
70     doc = document;
71   }
72   const extraStyle = doc.createElement('style');
73   doc.head.appendChild(extraStyle);
74   if (rules) {
75     const sheet = extraStyle.sheet;
76     for (const selector in rules) {
77       sheet.insertRule(`${selector}{${rules[selector]}}`,
78                        sheet.cssRules.length);
79     }
80   }
81   test.add_cleanup(() => {
82     extraStyle.remove();
83   });
84 }
85
86 // Create a pseudo element
87 function createPseudo(test, type) {
88   createStyle(test, { '@keyframes anim': '',
89                       [`.pseudo::${type}`]: 'animation: anim 10s; ' +
90                                             'content: \'\';'  });
91   const div = createDiv(test);
92   div.classList.add('pseudo');
93   const anims = document.getAnimations();
94   assert_true(anims.length >= 1);
95   const anim = anims[anims.length - 1];
96   assert_equals(anim.effect.target.parentElement, div);
97   assert_equals(anim.effect.target.type, `::${type}`);
98   anim.cancel();
99   return anim.effect.target;
100 }
101
102 // Cubic bezier with control points (0, 0), (x1, y1), (x2, y2), and (1, 1).
103 function cubicBezier(x1, y1, x2, y2) {
104   const xForT = t => {
105     const omt = 1-t;
106     return 3 * omt * omt * t * x1 + 3 * omt * t * t * x2 + t * t * t;
107   };
108
109   const yForT = t => {
110     const omt = 1-t;
111     return 3 * omt * omt * t * y1 + 3 * omt * t * t * y2 + t * t * t;
112   };
113
114   const tForX = x => {
115     // Binary subdivision.
116     let mint = 0, maxt = 1;
117     for (let i = 0; i < 30; ++i) {
118       const guesst = (mint + maxt) / 2;
119       const guessx = xForT(guesst);
120       if (x < guessx) {
121         maxt = guesst;
122       } else {
123         mint = guesst;
124       }
125     }
126     return (mint + maxt) / 2;
127   };
128
129   return x => {
130     if (x == 0) {
131       return 0;
132     }
133     if (x == 1) {
134       return 1;
135     }
136     return yForT(tForX(x));
137   };
138 }
139
140 function stepEnd(nsteps) {
141   return x => Math.floor(x * nsteps) / nsteps;
142 }
143
144 function stepStart(nsteps) {
145   return x => {
146     const result = Math.floor(x * nsteps + 1.0) / nsteps;
147     return (result > 1.0) ? 1.0 : result;
148   };
149 }
150
151 function framesTiming(nframes) {
152   return x => {
153     const result = Math.floor(x * nframes) / (nframes - 1);
154     return (result > 1.0 && x <= 1.0) ? 1.0 : result;
155   };
156 }
157
158 function waitForAnimationFrames(frameCount) {
159   return new Promise(resolve => {
160     function handleFrame() {
161       if (--frameCount <= 0) {
162         resolve();
163       } else {
164         window.requestAnimationFrame(handleFrame); // wait another frame
165       }
166     }
167     window.requestAnimationFrame(handleFrame);
168   });
169 }
170
171 // Continually calls requestAnimationFrame until |minDelay| has elapsed
172 // as recorded using document.timeline.currentTime (i.e. frame time not
173 // wall-clock time).
174 function waitForAnimationFramesWithDelay(minDelay) {
175   const startTime = document.timeline.currentTime;
176   return new Promise(resolve => {
177     (function handleFrame() {
178       if (document.timeline.currentTime - startTime >= minDelay) {
179         resolve();
180       } else {
181         window.requestAnimationFrame(handleFrame);
182       }
183     }());
184   });
185 }
186
187
188 // Waits for a requestAnimationFrame callback in the next refresh driver tick.
189 function waitForNextFrame() {
190   const timeAtStart = document.timeline.currentTime;
191   return new Promise(resolve => {
192     window.requestAnimationFrame(() => {
193       if (timeAtStart === document.timeline.currentTime) {
194         window.requestAnimationFrame(resolve);
195       } else {
196         resolve();
197       }
198     });
199   });
200 }
201
202 // Returns 'matrix()' or 'matrix3d()' function string generated from an array.
203 function createMatrixFromArray(array) {
204   return (array.length == 16 ? 'matrix3d' : 'matrix') + `(${array.join()})`;
205 }
206
207 // Returns 'matrix3d()' function string equivalent to
208 // 'rotate3d(x, y, z, radian)'.
209 function rotate3dToMatrix3d(x, y, z, radian) {
210   return createMatrixFromArray(rotate3dToMatrix(x, y, z, radian));
211 }
212
213 // Returns an array of the 4x4 matrix equivalent to 'rotate3d(x, y, z, radian)'.
214 // https://www.w3.org/TR/css-transforms-1/#Rotate3dDefined
215 function rotate3dToMatrix(x, y, z, radian) {
216   const sc = Math.sin(radian / 2) * Math.cos(radian / 2);
217   const sq = Math.sin(radian / 2) * Math.sin(radian / 2);
218
219   // Normalize the vector.
220   const length = Math.sqrt(x*x + y*y + z*z);
221   x /= length;
222   y /= length;
223   z /= length;
224
225   return [
226     1 - 2 * (y*y + z*z) * sq,
227     2 * (x * y * sq + z * sc),
228     2 * (x * z * sq - y * sc),
229     0,
230     2 * (x * y * sq - z * sc),
231     1 - 2 * (x*x + z*z) * sq,
232     2 * (y * z * sq + x * sc),
233     0,
234     2 * (x * z * sq + y * sc),
235     2 * (y * z * sq - x * sc),
236     1 - 2 * (x*x + y*y) * sq,
237     0,
238     0,
239     0,
240     0,
241     1
242   ];
243 }
244
245 // Compare matrix string like 'matrix(1, 0, 0, 1, 100, 0)' with tolerances.
246 function assert_matrix_equals(actual, expected, description) {
247   const matrixRegExp = /^matrix(?:3d)*\((.+)\)/;
248   assert_regexp_match(actual, matrixRegExp,
249     'Actual value is not a matrix')
250   assert_regexp_match(expected, matrixRegExp,
251     'Expected value is not a matrix');
252
253   const actualMatrixArray =
254     actual.match(matrixRegExp)[1].split(',').map(Number);
255   const expectedMatrixArray =
256     expected.match(matrixRegExp)[1].split(',').map(Number);
257
258   assert_equals(actualMatrixArray.length, expectedMatrixArray.length,
259     `dimension of the matrix: ${description}`);
260   for (let i = 0; i < actualMatrixArray.length; i++) {
261     assert_approx_equals(actualMatrixArray[i], expectedMatrixArray[i], 0.0001,
262       `expected ${expected} but got ${actual}: ${description}`);
263   }
264 }