[JSC] AI should not propagate AbstractValue relying on constant folding phase
[WebKit-https.git] / JSTests / stress / async-iteration-yield-star-interface.js
1 var assert = function (result, expected, message = "") {
2   if (result !== expected) {
3     throw new Error('Error in assert. Expected "' + expected + '" but was "' + result + '":' + message );
4   }
5 };
6
7 const getPromise = promiseHolder => {
8     return new Promise((resolve, reject) => {
9         promiseHolder.resolve = resolve;
10         promiseHolder.reject = reject;
11     });
12 };
13
14 const Logger = function () {
15     var log = [];
16
17     this.logEvent = (type, value, done) => {
18         log.push({ type, value, done});
19     };
20     this.logFulfilledEvent = (value, done) => {
21         this.logEvent('fulfilled', value, done);
22     };
23     this.logRejectEvent = error => {
24         this.logEvent('reject', error.toString(), true);
25     };
26     this.logCatchEvent = value => {
27         this.logEvent('catch', value, true);
28     };
29     this.logCustomEvent = event => {
30         this.logEvent('custom', event, false);
31     };
32     this.getLogger = () => log;
33
34     this.clear = () => {
35         log = [];
36     }
37 };
38
39 const fulfillSpy = logger => result => logger.logFulfilledEvent(result.value, result.done);
40 const rejectSpy = logger => error => logger.logRejectEvent(error);
41 const catchSpy = logger => error => logger.logCatchEvent(error);
42 const customSpy = logger => event => logger.logCustomEvent(event);
43
44 const assertLogger = function (loggerObject) {
45     const logger = loggerObject.getLogger();
46
47     var _assertLogger = function () {
48         let index = 0;
49
50         const isNotOutOfLength = () => {
51             assert(index < logger.length, true, `Index is greater then log length`);   
52         }
53
54         this.fullfilled = function (expectedValue, message = 'on fulfill') {
55             isNotOutOfLength();
56
57             const msg = `step: ${index} - ${message}`;
58             let step = logger[index];
59             assert(step.type, 'fulfilled', msg);
60             assert(step.value, expectedValue, msg);
61             assert(step.done, false, msg);
62
63             index++;
64             return this;
65         };
66
67         this.fullfilledDone = function (expectedValue, message = 'on fulfill with done true') {
68             isNotOutOfLength();
69
70             const msg = `step: ${index} - ${message}`;
71             let step = logger[index];
72
73             assert(step.type, 'fulfilled', msg);
74             assert(step.value, expectedValue, msg);
75             assert(step.done, true, msg);
76
77             index++;
78             return this;
79         };
80
81         this.rejected = function (error, message = 'on reject') {
82             isNotOutOfLength();
83
84             const msg = `step: ${index} - ${message}`;
85             let step = logger[index];
86
87             assert(step.type, 'reject', msg);
88             assert(step.value, error.toString(), msg);
89             assert(step.done, true, msg);
90
91             index++;
92             return this;
93         };
94
95         this.catched = function (expectedError, message = 'on catch') {
96             isNotOutOfLength();
97
98             const msg = `step: ${index} - ${message}`;
99             let step = logger[index];
100
101             assert(step.type, 'catch', msg);
102             assert(step.value, expectedError, msg);
103             assert(step.done, true, msg);
104
105             index++;
106             return this;
107         };
108
109         this.custom = function (expectedValue, message = 'on custom event') {
110
111             const msg = `step: ${index} - ${message}`;
112             let step = logger[index];
113
114             assert(step.type, 'custom', msg);
115             assert(step.value, expectedValue, msg);
116             assert(step.done, false, msg);
117
118             index++;
119             return this;
120         };
121
122         this.isFinal = function (message = '') {
123             assert(index, logger.length, `expected final step: ${message}`);
124         }; 
125     }; 
126     
127     return new _assertLogger();
128 };
129
130 var logger = new Logger();
131 const someValue = 'some-value';
132 const errorMessage = 'error-message';
133
134 let asyncIter = {
135     [Symbol.asyncIterator]() { return this; },
136     next (value) {
137         customSpy(logger)('next:' + value);
138         return { value: value, done: 'iter:Finish' === value };
139     },
140     throw (error) {
141         customSpy(logger)('throw:' + error);
142         return error;
143     },
144     return(value) {
145         customSpy(logger)('return:' + value);
146         return { value: value, done: true };
147     }
148   };
149
150 async function *foo () {
151     yield '0';
152     yield* asyncIter;
153     yield '3';
154 }
155
156 let f = foo('Init');
157
158 f.next('A').then(fulfillSpy(logger), rejectSpy(logger));
159 f.next('B').then(fulfillSpy(logger), rejectSpy(logger));
160 f.next('C').then(fulfillSpy(logger), rejectSpy(logger));
161 f.next('D').then(fulfillSpy(logger), rejectSpy(logger));
162 f.next('E').then(fulfillSpy(logger), rejectSpy(logger));
163 f.next('iter:Finish').then(fulfillSpy(logger), rejectSpy(logger));
164 f.next('Finish').then(fulfillSpy(logger), rejectSpy(logger));
165
166 drainMicrotasks();
167
168 assertLogger(logger)
169     .custom('next:undefined')
170     .fullfilled('0')
171     .custom('next:C')
172     .fullfilled(undefined)
173     .custom('next:D')
174     .fullfilled("C")
175     .custom('next:E')
176     .fullfilled("D")
177     .custom('next:iter:Finish')
178     .fullfilled("E")
179     .fullfilled("3")
180     .fullfilledDone(undefined)
181     .isFinal();
182
183 logger.clear();
184
185 f = foo('Init');
186
187 f.next('A').then(fulfillSpy(logger), rejectSpy(logger));
188 f.next('B').then(fulfillSpy(logger), rejectSpy(logger));
189 f.return('C').then(fulfillSpy(logger), rejectSpy(logger));
190 f.next('D').then(fulfillSpy(logger), rejectSpy(logger));
191 f.next('E').then(fulfillSpy(logger), rejectSpy(logger));
192 f.next('iter:Finish').then(fulfillSpy(logger), rejectSpy(logger));
193 f.next('Finish').then(fulfillSpy(logger), rejectSpy(logger));
194
195 drainMicrotasks();
196
197 assertLogger(logger)
198     .custom('next:undefined')
199     .fullfilled('0')
200     .custom('return:C')
201     .fullfilled(undefined)
202     .fullfilledDone("C")
203     .fullfilledDone(undefined)
204     .fullfilledDone(undefined)
205     .fullfilledDone(undefined)
206     .fullfilledDone(undefined)
207     .isFinal();
208
209 logger.clear();
210
211 f = foo('Init');
212
213 f.next('A').then(fulfillSpy(logger), rejectSpy(logger));
214 f.next('B').then(fulfillSpy(logger), rejectSpy(logger));
215 f.throw(new Error(errorMessage)).then(fulfillSpy(logger), rejectSpy(logger));
216 f.next('D').then(fulfillSpy(logger), rejectSpy(logger));
217 f.next('E').then(fulfillSpy(logger), rejectSpy(logger));
218 f.next('iter:Finish').then(fulfillSpy(logger), rejectSpy(logger));
219 f.next('Finish').then(fulfillSpy(logger), rejectSpy(logger));
220
221 drainMicrotasks();
222
223 assertLogger(logger)
224     .custom('next:undefined')
225     .fullfilled('0')
226     .custom('throw:' + new Error(errorMessage))
227     .fullfilled(undefined)
228     .custom('next:D')
229     .fullfilled(undefined)
230     .custom('next:E')
231     .fullfilled('D')
232     .custom('next:iter:Finish')
233     .fullfilled('E')
234     .fullfilled('3')
235     .fullfilledDone(undefined)
236     .isFinal();
237
238 asyncIter = {
239     [Symbol.asyncIterator]() { return this; },
240     next (value) {
241         customSpy(logger)('next:' + value);
242         return { value: value, done: 'iter:Finish' === value };
243     }
244   };
245
246 async function *boo () {
247     yield '0';
248     yield* asyncIter;
249     yield '3';
250 }
251
252 let b = boo('Init');
253
254 logger.clear();
255
256 b.next('A').then(fulfillSpy(logger), rejectSpy(logger));
257 b.next('B').then(fulfillSpy(logger), rejectSpy(logger));
258 b.next('C').then(fulfillSpy(logger), rejectSpy(logger));
259 b.next('D').then(fulfillSpy(logger), rejectSpy(logger));
260 b.next('iter:Finish').then(fulfillSpy(logger), rejectSpy(logger));
261 b.next('Finish').then(fulfillSpy(logger), rejectSpy(logger));
262
263 drainMicrotasks();
264
265 assertLogger(logger)
266     .custom('next:undefined')
267     .fullfilled('0')
268     .custom('next:C')
269     .fullfilled(undefined)
270     .custom('next:D')
271     .fullfilled("C")
272     .custom("next:iter:Finish")
273     .fullfilled("D")
274     .fullfilled("3")
275     .fullfilledDone(undefined)
276     .isFinal();
277
278 logger.clear();
279
280 b = boo('Init');
281
282 b.next('A').then(fulfillSpy(logger), rejectSpy(logger));
283 b.next('B').then(fulfillSpy(logger), rejectSpy(logger));
284 b.throw(new Error(errorMessage)).then(fulfillSpy(logger), rejectSpy(logger));
285 b.next('D').then(fulfillSpy(logger), rejectSpy(logger));
286 b.next('iter:Finish').then(fulfillSpy(logger), rejectSpy(logger));
287 b.next('Finish').then(fulfillSpy(logger), rejectSpy(logger));
288
289 drainMicrotasks();
290
291 assertLogger(logger)
292     .custom('next:undefined')
293     .fullfilled('0')
294     .fullfilled(undefined)
295     .rejected('TypeError: Delegated generator does not have a \'throw\' method.')
296     .fullfilledDone(undefined)
297     .fullfilledDone(undefined)
298     .fullfilledDone(undefined)
299     .isFinal();
300
301 asyncIter = {
302     [Symbol.asyncIterator]() { return this; },
303     next (value) {
304         customSpy(logger)('next:' + value);
305         return { value: value, done: 'iter:Finish' === value };
306     },
307     return (value) {
308         customSpy(logger)('return:' + value);
309         return { value: value, done: true };
310     }
311   };
312
313 async function *bar () {
314     yield '0';
315     yield* asyncIter;
316     yield '3';
317 }
318
319 b = bar('Init');
320
321 logger.clear();
322
323 b.next('A').then(fulfillSpy(logger), rejectSpy(logger));
324 b.next('B').then(fulfillSpy(logger), rejectSpy(logger));
325 b.throw(new Error(errorMessage)).then(fulfillSpy(logger), rejectSpy(logger));
326 b.next('D').then(fulfillSpy(logger), rejectSpy(logger));
327 b.next('iter:Finish').then(fulfillSpy(logger), rejectSpy(logger));
328 b.next('Finish').then(fulfillSpy(logger), rejectSpy(logger));
329
330 drainMicrotasks();
331
332 assertLogger(logger)
333     .custom('next:undefined')
334     .fullfilled('0')
335     .custom('return:undefined')
336     .fullfilled(undefined)
337     .rejected('TypeError: Delegated generator does not have a \'throw\' method.')
338     .fullfilledDone(undefined)
339     .fullfilledDone(undefined)
340     .fullfilledDone(undefined)
341     .isFinal();
342
343 let ph = {};
344
345 asyncIter = {
346     [Symbol.asyncIterator]() { return this; },
347     next (value) {
348         customSpy(logger)('next:' + value);
349         return { value: value, done: 'iter:Finish' === value };
350     },
351     return (value) {
352         customSpy(logger)('return:' + value);
353         return { value: getPromise(ph), done: true };
354     }
355   };
356
357 async function *baz () {
358     yield '0';
359     yield* asyncIter;
360     yield '3';
361 }
362
363 b = baz('Init');
364
365 logger.clear();
366
367 b.next('A').then(fulfillSpy(logger), rejectSpy(logger));
368 b.next('B').then(fulfillSpy(logger), rejectSpy(logger));
369 b.throw(new Error(errorMessage)).then(fulfillSpy(logger), rejectSpy(logger));
370 b.next('D').then(fulfillSpy(logger), rejectSpy(logger));
371 b.next('iter:Finish').then(fulfillSpy(logger), rejectSpy(logger));
372 b.next('Finish').then(fulfillSpy(logger), rejectSpy(logger));
373
374 drainMicrotasks();
375
376 assertLogger(logger)
377     .custom('next:undefined')
378     .fullfilled('0')
379     .custom('return:undefined')
380     .fullfilled(undefined)
381     .rejected('TypeError: Delegated generator does not have a \'throw\' method.')
382     .fullfilledDone(undefined)
383     .fullfilledDone(undefined)
384     .fullfilledDone(undefined)
385     .isFinal();
386
387 ph.resolve('accept');
388
389 drainMicrotasks();
390
391 assertLogger(logger)
392     .custom('next:undefined')
393     .fullfilled('0')
394     .custom('return:undefined')
395     .fullfilled(undefined)
396     .rejected('TypeError: Delegated generator does not have a \'throw\' method.')
397     .fullfilledDone(undefined)
398     .fullfilledDone(undefined)
399     .fullfilledDone(undefined)
400     .isFinal();
401
402 ph = {};
403
404 asyncIter = {
405     [Symbol.asyncIterator]() { return this; },
406     next (value) {
407         customSpy(logger)('next:' + value);
408         return { value: value, done: 'iter:Finish' === value };
409     },
410     return (value) {
411         customSpy(logger)('return:' + value);
412         return getPromise(ph);
413     }
414   };
415
416 async function *foobar () {
417     yield '0';
418     yield* asyncIter;
419     yield '3';
420 }
421
422 fb = foobar('Init');
423
424 logger.clear();
425
426 fb.next('A').then(fulfillSpy(logger), rejectSpy(logger));
427 fb.next('B').then(fulfillSpy(logger), rejectSpy(logger));
428 fb.throw(new Error(errorMessage)).then(fulfillSpy(logger), rejectSpy(logger));
429 fb.next('D').then(fulfillSpy(logger), rejectSpy(logger));
430 fb.next('iter:Finish').then(fulfillSpy(logger), rejectSpy(logger));
431 fb.next('Finish').then(fulfillSpy(logger), rejectSpy(logger));
432
433 drainMicrotasks();
434
435 assertLogger(logger)
436     .custom('next:undefined')
437     .fullfilled('0')
438     .custom('return:undefined')
439     .fullfilled(undefined)
440     .isFinal();
441
442 ph.resolve({ value: 'value', done: true });
443
444 drainMicrotasks();
445
446 assertLogger(logger)
447     .custom('next:undefined')
448     .fullfilled('0')
449     .custom('return:undefined')
450     .fullfilled(undefined)
451     .rejected('TypeError: Delegated generator does not have a \'throw\' method.')
452     .fullfilledDone(undefined)
453     .fullfilledDone(undefined)
454     .fullfilledDone(undefined)
455     .isFinal();
456
457 fb = foobar('Init');
458
459 logger.clear();
460
461 fb.next('A').then(fulfillSpy(logger), rejectSpy(logger));
462 fb.next('B').then(fulfillSpy(logger), rejectSpy(logger));
463 fb.throw(new Error(errorMessage)).then(fulfillSpy(logger), rejectSpy(logger));
464 fb.next('D').then(fulfillSpy(logger), rejectSpy(logger));
465 fb.next('iter:Finish').then(fulfillSpy(logger), rejectSpy(logger));
466 fb.next('Finish').then(fulfillSpy(logger), rejectSpy(logger));
467
468 drainMicrotasks();
469
470 assertLogger(logger)
471     .custom('next:undefined')
472     .fullfilled('0')
473     .custom('return:undefined')
474     .fullfilled(undefined)
475     .isFinal();
476
477 ph.resolve('X');
478
479 drainMicrotasks();
480
481 assertLogger(logger)
482     .custom('next:undefined')
483     .fullfilled('0')
484     .custom('return:undefined')
485     .fullfilled(undefined)
486     .rejected('TypeError: Iterator result interface is not an object.')
487     .fullfilledDone(undefined)
488     .fullfilledDone(undefined)
489     .fullfilledDone(undefined)
490     .isFinal();