View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.javascript.host;
16  
17  import org.htmlunit.WebDriverTestCase;
18  import org.htmlunit.corejs.javascript.NativePromise;
19  import org.htmlunit.junit.BrowserRunner;
20  import org.htmlunit.junit.annotation.Alerts;
21  import org.junit.Test;
22  import org.junit.runner.RunWith;
23  import org.openqa.selenium.By;
24  import org.openqa.selenium.WebDriver;
25  
26  /**
27   * Tests for {@link NativePromise}.
28   *
29   * @author Ahmed Ashour
30   * @author Marc Guillemot
31   * @author Madis Pärn
32   * @author Ronald Brill
33   * @author Rural Hunter
34   */
35  @RunWith(BrowserRunner.class)
36  public class PromiseTest extends WebDriverTestCase {
37  
38      /**
39       * @throws Exception if an error occurs
40       */
41      @Test
42      @Alerts({"function", "function", "undefined", "undefined",
43               "undefined", "undefined", "function", "function"})
44      public void staticMethods() throws Exception {
45          final String html = DOCTYPE_HTML
46              + "<html>\n"
47              + "<head>\n"
48              + "  <script>\n"
49              + LOG_TITLE_FUNCTION
50              + "    function test() {\n"
51              + "      if (window.Promise) {\n"
52              + "        log(typeof Promise.resolve);\n"
53              + "        log(typeof Promise.reject);\n"
54              + "        log(typeof Promise.then);\n"
55              + "        log(typeof Promise.catch);\n"
56              + "        var p = Promise.resolve('something');\n"
57              + "        log(typeof p.resolve);\n"
58              + "        log(typeof p.reject);\n"
59              + "        log(typeof p.then);\n"
60              + "        log(typeof p.catch);\n"
61              + "      }\n"
62              + "    }\n"
63              + "  </script>\n"
64              + "</head>\n"
65              + "<body onload='test()'>\n"
66              + "</body>\n"
67              + "</html>";
68  
69          loadPageVerifyTitle2(html);
70      }
71  
72      /**
73       * @throws Exception if an error occurs
74       */
75      @Test
76      @Alerts("1")
77      public void length() throws Exception {
78          final String html =
79              "<html>\n"
80              + "<head>\n"
81              + "  <script>\n"
82              + LOG_TEXTAREA_FUNCTION
83              + "    function test() {\n"
84              + "      if (window.Promise) {\n"
85              + "        log(Promise.length);\n"
86              + "      }\n"
87              + "    }\n"
88              + "  </script>\n"
89              + "</head>\n"
90              + "<body onload='test()'>\n"
91              + LOG_TEXTAREA
92              + "</body>\n"
93              + "</html>";
94  
95          loadPageVerifyTextArea2(html);
96      }
97  
98      /**
99       * @throws Exception if an error occurs
100      */
101     @Test
102     @Alerts(DEFAULT = {"function () { [native code] }",
103                        "function () { [native code] }",
104                        "[object Window]",
105                        "done", "resolved value"},
106             FF = {"function () {\n    [native code]\n}",
107                   "function () {\n    [native code]\n}",
108                   "[object Window]",
109                   "done", "resolved value"},
110             FF_ESR = {"function () {\n    [native code]\n}",
111                       "function () {\n    [native code]\n}",
112                       "[object Window]",
113                       "done", "resolved value"})
114     public void constructor() throws Exception {
115         final String html = DOCTYPE_HTML
116                 + "<html>\n"
117                 + "<head>\n"
118                 + "  <script>\n"
119                 + LOG_TEXTAREA_FUNCTION
120                 + "    function test() {\n"
121                 + "      if (window.Promise) {\n"
122                 + "        var p = new Promise(function(resolve, reject) {\n"
123                 + "          log(resolve);\n"
124                 + "          log(reject);\n"
125                 + "          log(this);\n"
126                 + "          resolve('resolved value');\n"
127                 + "        });\n"
128                 + "        p.then(function(value) {log(value);});\n"
129                 + "        log('done');\n"
130                 + "      }\n"
131                 + "    }\n"
132                 + "\n"
133                 + "  </script>\n"
134                 + "</head>\n"
135                 + "<body onload='test()'>\n"
136                 + LOG_TEXTAREA
137                 + "</body>\n"
138                 + "</html>";
139 
140         loadPageVerifyTextArea2(html);
141     }
142 
143     /**
144      * @throws Exception if an error occurs
145      */
146     @Test
147     @Alerts(DEFAULT = {"function () { [native code] }",
148                        "function () { [native code] }",
149                        "undefined",
150                        "done", "resolved value"},
151             FF = {"function () {\n    [native code]\n}",
152                   "function () {\n    [native code]\n}",
153                   "undefined",
154                   "done", "resolved value"},
155             FF_ESR = {"function () {\n    [native code]\n}",
156                       "function () {\n    [native code]\n}",
157                       "undefined",
158                       "done", "resolved value"})
159     public void constructorStrict() throws Exception {
160         final String html = DOCTYPE_HTML
161                 + "<html>\n"
162                 + "<head>\n"
163                 + "  <script>\n"
164                 + "    'use strict';"
165                 + LOG_TEXTAREA_FUNCTION
166                 + "    function test() {\n"
167                 + "      if (window.Promise) {\n"
168                 + "        var p = new Promise(function(resolve, reject) {\n"
169                 + "          log(resolve);\n"
170                 + "          log(reject);\n"
171                 + "          log(this);\n"
172                 + "          resolve('resolved value');\n"
173                 + "        });\n"
174                 + "        p.then(function(value) {log(value);});\n"
175                 + "        log('done');\n"
176                 + "      }\n"
177                 + "    }\n"
178                 + "\n"
179                 + "  </script>\n"
180                 + "</head>\n"
181                 + "<body onload='test()'>\n"
182                 + LOG_TEXTAREA
183                 + "</body>\n"
184                 + "</html>";
185 
186         loadPageVerifyTextArea2(html);
187     }
188 
189     /**
190      * @throws Exception if an error occurs
191      */
192     @Test
193     @Alerts({"true", "true", "true"})
194     public void constructorWithoutFunction() throws Exception {
195         final String html = DOCTYPE_HTML
196                 + "<html>\n"
197                 + "<head>\n"
198                 + "  <script>\n"
199                 + LOG_TEXTAREA_FUNCTION
200                 + "    function test() {\n"
201                 + "      if (window.Promise) {\n"
202                 + "        try{\n"
203                 + "          var p = new Promise();\n"
204                 + "          log('done');\n"
205                 + "        } catch(e) { log(e instanceof TypeError); }\n"
206 
207                 + "        try{\n"
208                 + "          var p = new Promise([1, 2, 4]);\n"
209                 + "          log('done');\n"
210                 + "        } catch(e) { log(e instanceof TypeError); }\n"
211 
212                 + "        try{\n"
213                 + "          var original = Promise.resolve(42);\n"
214                 + "          var p = new Promise(original);\n"
215                 + "          log('done');\n"
216                 + "        } catch(e) { log(e instanceof TypeError); }\n"
217                 + "      }\n"
218                 + "    }\n"
219                 + "\n"
220                 + "  </script>\n"
221                 + "</head>\n"
222                 + "<body onload='test()'>\n"
223                 + LOG_TEXTAREA
224                 + "</body>\n"
225                 + "</html>";
226 
227         loadPageVerifyTextArea2(html);
228     }
229 
230     /**
231      * @throws Exception if an error occurs
232      */
233     @Test
234     @Alerts({"done", "Rejected"})
235     public void reject() throws Exception {
236         final String html = DOCTYPE_HTML
237             + "<html>\n"
238             + "<head>\n"
239             + "  <script>\n"
240             + LOG_TEXTAREA_FUNCTION
241             + "    function test() {\n"
242             + "      if (window.Promise) {\n"
243             + "        Promise.reject('Rejected').then(function(value) {\n"
244             + "            log('failure');\n"
245             + "        }, function(value) {\n"
246             + "            log(value);\n"
247             + "        });\n"
248             + "        log('done');\n"
249             + "      }\n"
250             + "    }\n"
251             + "  </script>\n"
252             + "</head>\n"
253             + "<body onload='test()'>\n"
254             + LOG_TEXTAREA
255             + "</body>\n"
256             + "</html>";
257 
258         loadPageVerifyTextArea2(html);
259     }
260 
261     /**
262      * @throws Exception if an error occurs
263      */
264     @Test
265     @Alerts({"done", "false", "[object Promise]"})
266     public void rejectPromise() throws Exception {
267         final String html = DOCTYPE_HTML
268             + "<html>\n"
269             + "<head>\n"
270             + "  <script>\n"
271             + LOG_TEXTAREA_FUNCTION
272             + "    function test() {\n"
273             + "      if (window.Promise) {\n"
274             + "        var original = Promise.reject(42);\n"
275             + "        var cast = Promise.reject(original);\n"
276             + "        cast.then(function(v) {\n"
277             + "          log('failure');\n"
278             + "        }, function(value) {\n"
279             + "          log(value);\n"
280             + "        });\n"
281             + "        log('done');\n"
282             + "        log(original === cast);\n"
283             + "      }\n"
284             + "    }\n"
285             + "  </script>\n"
286             + "</head>\n"
287             + "<body onload='test()'>\n"
288             + LOG_TEXTAREA
289             + "</body>\n"
290             + "</html>";
291 
292         loadPageVerifyTextArea2(html);
293     }
294 
295     /**
296      * @throws Exception if an error occurs
297      */
298     @Test
299     @Alerts({"done", "Resolved"})
300     public void resolve() throws Exception {
301         final String html = DOCTYPE_HTML
302             + "<html>\n"
303             + "<head>\n"
304             + "  <script>\n"
305             + LOG_TEXTAREA_FUNCTION
306             + "    function test() {\n"
307             + "      if (window.Promise) {\n"
308             + "        Promise.resolve('Resolved').then(function(value) {\n"
309             + "            log(value);\n"
310             + "        }, function(value) {\n"
311             + "            log('failure');\n"
312             + "        });\n"
313             + "        log('done');\n"
314             + "      }\n"
315             + "    }\n"
316             + "  </script>\n"
317             + "</head>\n"
318             + "<body onload='test()'>\n"
319             + LOG_TEXTAREA
320             + "</body>\n"
321             + "</html>";
322 
323         loadPageVerifyTextArea2(html);
324     }
325 
326     /**
327      * @throws Exception if an error occurs
328      */
329     @Test
330     @Alerts({"done", "undefined"})
331     public void resolveEmpty() throws Exception {
332         final String html = DOCTYPE_HTML
333             + "<html>\n"
334             + "<head>\n"
335             + "  <script>\n"
336             + LOG_TEXTAREA_FUNCTION
337             + "    function test() {\n"
338             + "      if (window.Promise) {\n"
339             + "        Promise.resolve().then(function(value) {\n"
340             + "            log(value);\n"
341             + "        }, function(value) {\n"
342             + "            log('failure');\n"
343             + "        });\n"
344             + "        log('done');\n"
345             + "      }\n"
346             + "    }\n"
347             + "  </script>\n"
348             + "</head>\n"
349             + "<body onload='test()'>\n"
350             + LOG_TEXTAREA
351             + "</body>\n"
352             + "</html>";
353 
354         loadPageVerifyTextArea2(html);
355     }
356 
357     /**
358      * @throws Exception if an error occurs
359      */
360     @Test
361     @Alerts({"done", "1"})
362     public void resolveArray() throws Exception {
363         final String html = DOCTYPE_HTML
364             + "<html>\n"
365             + "<head>\n"
366             + "  <script>\n"
367             + LOG_TEXTAREA_FUNCTION
368             + "    function test() {\n"
369             + "      if (window.Promise) {\n"
370             + "        var p = Promise.resolve([1,2,3]);\n"
371             + "        p.then(function(v) {\n"
372             + "            log(v[0]);\n"
373             + "        });\n"
374             + "        log('done');\n"
375             + "      }\n"
376             + "    }\n"
377             + "  </script>\n"
378             + "</head>\n"
379             + "<body onload='test()'>\n"
380             + LOG_TEXTAREA
381             + "</body>\n"
382             + "</html>";
383 
384         loadPageVerifyTextArea2(html);
385     }
386 
387     /**
388      * @throws Exception if an error occurs
389      */
390     @Test
391     @Alerts({"done", "HtmlUnit"})
392     public void resolveString() throws Exception {
393         final String html = DOCTYPE_HTML
394             + "<html>\n"
395             + "<head>\n"
396             + "  <script>\n"
397             + LOG_TEXTAREA_FUNCTION
398             + "    function test() {\n"
399             + "      if (window.Promise) {\n"
400             + "        var p = Promise.resolve('HtmlUnit');\n"
401             + "        p.then(function(v) {\n"
402             + "            log(v);\n"
403             + "        });\n"
404             + "        log('done');\n"
405             + "      }\n"
406             + "    }\n"
407             + "  </script>\n"
408             + "</head>\n"
409             + "<body onload='test()'>\n"
410             + LOG_TEXTAREA
411             + "</body>\n"
412             + "</html>";
413 
414         loadPageVerifyTextArea2(html);
415     }
416 
417     /**
418      * @throws Exception if an error occurs
419      */
420     @Test
421     @Alerts({"done", "true", "42"})
422     public void resolvePromise() throws Exception {
423         final String html = DOCTYPE_HTML
424             + "<html>\n"
425             + "<head>\n"
426             + "  <script>\n"
427             + LOG_TEXTAREA_FUNCTION
428             + "    function test() {\n"
429             + "      if (window.Promise) {\n"
430             + "        var original = Promise.resolve(42);\n"
431             + "        var cast = Promise.resolve(original);\n"
432             + "        cast.then(function(v) {\n"
433             + "          log(v);\n"
434             + "        });\n"
435             + "        log('done');\n"
436             + "        log(original === cast);\n"
437             + "      }\n"
438             + "    }\n"
439             + "  </script>\n"
440             + "</head>\n"
441             + "<body onload='test()'>\n"
442             + LOG_TEXTAREA
443             + "</body>\n"
444             + "</html>";
445 
446         loadPageVerifyTextArea2(html);
447     }
448 
449     /**
450      * @throws Exception if an error occurs
451      */
452     @Test
453     @Alerts({"true", "fulfilled!"})
454     public void resolveThenable() throws Exception {
455         final String html = DOCTYPE_HTML
456             + "<html>\n"
457             + "<head>\n"
458             + "  <script>\n"
459             + LOG_TEXTAREA_FUNCTION
460             + "    function test() {\n"
461             + "      if (window.Promise) {\n"
462 
463             + "        var p1 = Promise.resolve({\n"
464             + "          then: function(onFulfill, onReject) {\n"
465             + "            onFulfill('fulfilled!');\n"
466             + "          }\n"
467             + "        });\n"
468             + "        log(p1 instanceof Promise);\n"
469             + "\n"
470             + "        p1.then(function(v) {\n"
471             + "            log(v);\n"
472             + "        }, function(e) {\n"
473             + "            log('failure');\n"
474             + "        });\n"
475 
476             + "      }\n"
477             + "    }\n"
478             + "  </script>\n"
479             + "</head>\n"
480             + "<body onload='test()'>\n"
481             + LOG_TEXTAREA
482             + "</body>\n"
483             + "</html>";
484 
485         loadPageVerifyTextArea2(html);
486     }
487 
488     /**
489      * @throws Exception if an error occurs
490      */
491     @Test
492     @Alerts({"true", "aaa"})
493     public void resolveThenablePrototype() throws Exception {
494         final String html = DOCTYPE_HTML
495             + "<html>\n"
496             + "<head>\n"
497             + "  <script>\n"
498             + LOG_TEXTAREA_FUNCTION
499             + "    function test() {\n"
500             + "      if (window.Promise) {\n"
501             + "        function MyThenable() {\n"
502             + "          this.value = 'aaa';\n"
503             + "        };"
504             + "        MyThenable.prototype = { then: function(onFulfill, onReject) { onFulfill(this.value); }};\n"
505             + "        var thenable = new MyThenable();\n"
506             + "        var p1 = Promise.resolve(1);\n"
507             + "        log(p1 instanceof Promise);\n"
508             + "\n"
509             + "        p1=p1.then(function(v) {\n"
510             + "            return thenable;\n"
511             + "        }, function(e) {\n"
512             + "            log('failure');\n"
513             + "        });\n"
514             + "\n"
515             + "        p1=p1.then(function(v) {\n"
516             + "            log(v);\n"
517             + "        }, function(e) {\n"
518             + "            log('failure');\n"
519             + "        });\n"
520 
521             + "      }\n"
522             + "    }\n"
523             + "  </script>\n"
524             + "</head>\n"
525             + "<body onload='test()'>\n"
526             + LOG_TEXTAREA
527             + "</body>\n"
528             + "</html>";
529 
530         loadPageVerifyTextArea2(html);
531     }
532 
533     /**
534      * @throws Exception if an error occurs
535      */
536     @Test
537     @Alerts("TypeError: Throwing 1")
538     public void resolveThenableThrows() throws Exception {
539         final String html = DOCTYPE_HTML
540             + "<html>\n"
541             + "<head>\n"
542             + "  <script>\n"
543             + LOG_TEXTAREA_FUNCTION
544             + "    function test() {\n"
545             + "      if (window.Promise) {\n"
546 
547             + "        var thenable = {\n"
548             + "          then: function(resolve) {\n"
549             + "            throw new TypeError('Throwing 1');\n"
550             + "            resolve(\"Resolving\");\n"
551             + "          }\n"
552             + "        };\n"
553             + "\n"
554             + "        var p2 = Promise.resolve(thenable);\n"
555             + "        p2.then(function(v) {\n"
556             + "          log('failure');\n"
557             + "        }, function(e) {\n"
558             + "          log(e);\n"
559             + "        });\n"
560 
561             + "      }\n"
562             + "    }\n"
563             + "  </script>\n"
564             + "</head>\n"
565             + "<body onload='test()'>\n"
566             + LOG_TEXTAREA
567             + "</body>\n"
568             + "</html>";
569 
570         loadPageVerifyTextArea2(html);
571     }
572 
573     /**
574      * @throws Exception if an error occurs
575      */
576     @Test
577     @Alerts("Resolving")
578     public void resolveThenableThrowsAfterCallback() throws Exception {
579         final String html = DOCTYPE_HTML
580             + "<html>\n"
581             + "<head>\n"
582             + "  <script>\n"
583             + LOG_TEXTAREA_FUNCTION
584             + "    function test() {\n"
585             + "      if (window.Promise) {\n"
586 
587             + "        var thenable = {\n"
588             + "          then: function(resolve) {\n"
589             + "            resolve('Resolving');\n"
590             + "            throw new TypeError('Throwing 2');\n"
591             + "          }\n"
592             + "        };\n"
593             + "\n"
594             + "        var p3 = Promise.resolve(thenable);\n"
595             + "        p3.then(function(v) {\n"
596             + "          log(v);\n"
597             + "        }, function(e) {\n"
598             + "          log('failure');\n"
599             + "        });\n"
600             + "      }\n"
601             + "    }\n"
602             + "  </script>\n"
603             + "</head>\n"
604             + "<body onload='test()'>\n"
605             + LOG_TEXTAREA
606             + "</body>\n"
607             + "</html>";
608 
609         loadPageVerifyTextArea2(html);
610     }
611 
612     /**
613      * @throws Exception if an error occurs
614      */
615     @Test
616     @Alerts({"true", "[object Object]"})
617     public void resolveThenablesWithoutThen() throws Exception {
618         final String html = DOCTYPE_HTML
619             + "<html>\n"
620             + "<head>\n"
621             + "  <script>\n"
622             + LOG_TEXTAREA_FUNCTION
623             + "    function test() {\n"
624             + "      if (window.Promise) {\n"
625             + "        var p1 = Promise.resolve({ id: 17 });\n"
626             + "        log(p1 instanceof Promise);\n"
627             + "\n"
628             + "        p1.then(function(v) {\n"
629             + "            log(v);\n"
630             + "        }, function(e) {\n"
631             + "            log('failure');\n"
632             + "        });\n"
633             + "      }\n"
634             + "    }\n"
635             + "  </script>\n"
636             + "</head>\n"
637             + "<body onload='test()'>\n"
638             + LOG_TEXTAREA
639             + "</body>\n"
640             + "</html>";
641 
642         loadPageVerifyTextArea2(html);
643     }
644 
645     /**
646      * @throws Exception if an error occurs
647      */
648     @Test
649     @Alerts({"done", "1", "2"})
650     public void thenChanining() throws Exception {
651         final String html = DOCTYPE_HTML
652             + "<html>\n"
653             + "<head>\n"
654             + "  <script>\n"
655             + LOG_TEXTAREA_FUNCTION
656             + "    function test() {\n"
657             + "      if (window.Promise) {\n"
658             + "        var p = new Promise(function(resolve, reject) {\n"
659             + "          resolve(1);\n"
660             + "        });\n"
661             + "\n"
662             + "        p.then(function(value) {\n"
663             + "          log(value);\n"
664             + "          return value + 1;\n"
665             + "        }).then(function(value) {\n"
666             + "          log(value);\n"
667             + "        });\n"
668             + "        log('done');\n"
669             + "      }\n"
670             + "    }\n"
671             + "  </script>\n"
672             + "</head>\n"
673             + "<body onload='test()'>\n"
674             + LOG_TEXTAREA
675             + "</body>\n"
676             + "</html>";
677 
678         loadPageVerifyTextArea2(html);
679     }
680 
681     /**
682      * @throws Exception if an error occurs
683      */
684     @Test
685     @Alerts({"done", "undefined"})
686     public void then() throws Exception {
687         final String html = DOCTYPE_HTML
688                 + "<html>\n"
689                 + "<head>\n"
690                 + "  <script>\n"
691                 + LOG_TEXTAREA_FUNCTION
692                 + "    function test() {\n"
693                 + "      if (window.Promise) {\n"
694                 + "        var p = Promise.resolve(void 0);\n"
695                 + "        p.then(function(value) {\n"
696                 + "          log(value);\n"
697                 + "        })\n"
698                 + "        log('done');\n"
699                 + "      }\n"
700                 + "    }\n"
701                 + "  </script>\n"
702                 + "</head>\n"
703                 + "<body onload='test()'>\n"
704                 + LOG_TEXTAREA
705                 + "</body>\n"
706                 + "</html>";
707 
708         loadPageVerifyTextArea2(html);
709     }
710 
711     /**
712      * @throws Exception if an error occurs
713      */
714     @Test
715     @Alerts({"done", "undefined"})
716     public void thenAsync() throws Exception {
717         final String html = DOCTYPE_HTML
718                 + "<html>\n"
719                 + "<head>\n"
720                 + "  <script>\n"
721                 + LOG_TEXTAREA_FUNCTION
722                 + "    function test() {\n"
723                 + "      if (window.Promise) {\n"
724                 + "        var p = new Promise(function(resolve, reject) {\n"
725                 + "           window.setTimeout( function() {\n"
726                 + "             resolve(void 0);\n"
727                 + "           }, 20);\n"
728                 + "        })\n"
729                 + "        p.then(function(value) {\n"
730                 + "          log(value);\n"
731                 + "        })\n"
732                 + "        log('done');\n"
733                 + "      }\n"
734                 + "    }\n"
735                 + "  </script>\n"
736                 + "</head>\n"
737                 + "<body onload='test()'>\n"
738                 + LOG_TEXTAREA
739                 + "</body>\n"
740                 + "</html>";
741 
742         loadPageVerifyTextArea2(html);
743     }
744 
745     /**
746      * @throws Exception if an error occurs
747      */
748     @Test
749     @Alerts({"done", "1 yes", "2 yes"})
750     public void thenTwice() throws Exception {
751         final String html = DOCTYPE_HTML
752                 + "<html>\n"
753                 + "<head>\n"
754                 + "  <script>\n"
755                 + LOG_TEXTAREA_FUNCTION
756                 + "    function test() {\n"
757                 + "      if (window.Promise) {\n"
758                 + "        var p = Promise.resolve('yes');\n"
759                 + "        p.then(function(value) {\n"
760                 + "          log('1 ' + value);\n"
761                 + "        })\n"
762                 + "        p.then(function(value) {\n"
763                 + "          log('2 ' + value);\n"
764                 + "        })\n"
765                 + "        log('done');\n"
766                 + "      }\n"
767                 + "    }\n"
768                 + "  </script>\n"
769                 + "</head>\n"
770                 + "<body onload='test()'>\n"
771                 + LOG_TEXTAREA
772                 + "</body>\n"
773                 + "</html>";
774 
775         loadPageVerifyTextArea2(html);
776     }
777 
778     /**
779      * @throws Exception if an error occurs
780      */
781     @Test
782     @Alerts({"done", "1 yes", "2 yes"})
783     public void thenTwiceAsync() throws Exception {
784         final String html = DOCTYPE_HTML
785                 + "<html>\n"
786                 + "<head>\n"
787                 + "  <script>\n"
788                 + LOG_TEXTAREA_FUNCTION
789                 + "    function test() {\n"
790                 + "      if (window.Promise) {\n"
791                 + "        var p = new Promise(function(resolve, reject) {\n"
792                 + "           window.setTimeout( function() {\n"
793                 + "             resolve('yes');\n"
794                 + "           }, 20);\n"
795                 + "        })\n"
796                 + "        p.then(function(value) {\n"
797                 + "          log('1 ' + value);\n"
798                 + "        })\n"
799                 + "        p.then(function(value) {\n"
800                 + "          log('2 ' + value);\n"
801                 + "        })\n"
802                 + "        log('done');\n"
803                 + "      }\n"
804                 + "    }\n"
805                 + "  </script>\n"
806                 + "</head>\n"
807                 + "<body onload='test()'>\n"
808                 + LOG_TEXTAREA
809                 + "</body>\n"
810                 + "</html>";
811 
812         loadPageVerifyTextArea2(html);
813     }
814 
815     /**
816      * @throws Exception if an error occurs
817      */
818     @Test
819     @Alerts({"done", "first", "second"})
820     public void thenAsyncPromiseResolved() throws Exception {
821         final String html = DOCTYPE_HTML
822                 + "<html>\n"
823                 + "<head>\n"
824                 + "  <script>\n"
825                 + LOG_TEXTAREA_FUNCTION
826                 + "    function test() {\n"
827                 + "      if (window.Promise) {\n"
828                 + "        var p = new Promise(function(resolve, reject) {\n"
829                 + "           window.setTimeout( function() {\n"
830                 + "             resolve('first');\n"
831                 + "           }, 20);\n"
832                 + "        })\n"
833                 + "        var p2 = p.then(function(value) {\n"
834                 + "          log(value);\n"
835                 + "          return Promise.resolve('second');"
836                 + "        })\n"
837                 + "        p2.then(function(value) {\n"
838                 + "          log(value);\n"
839                 + "        })\n"
840                 + "        log('done');\n"
841                 + "      }\n"
842                 + "    }\n"
843                 + "  </script>\n"
844                 + "</head>\n"
845                 + "<body onload='test()'>\n"
846                 + LOG_TEXTAREA
847                 + "</body>\n"
848                 + "</html>";
849 
850         loadPageVerifyTextArea2(html);
851     }
852 
853     /**
854      * @throws Exception if an error occurs
855      */
856     @Test
857     @Alerts({"done", "first", "second"})
858     public void thenAsyncPromiseRejected() throws Exception {
859         final String html = DOCTYPE_HTML
860                 + "<html>\n"
861                 + "<head>\n"
862                 + "  <script>\n"
863                 + LOG_TEXTAREA_FUNCTION
864                 + "    function test() {\n"
865                 + "      if (window.Promise) {\n"
866                 + "        var p = new Promise(function(resolve, reject) {\n"
867                 + "           window.setTimeout( function() {\n"
868                 + "             resolve('first');\n"
869                 + "           }, 20);\n"
870                 + "        })\n"
871                 + "        var p2 = p.then(function(value) {\n"
872                 + "          log(value);\n"
873                 + "          return Promise.reject('second');"
874                 + "        })\n"
875                 + "        p2.then(function(value) {\n"
876                 + "          log('Failure');\n"
877                 + "        },"
878                 + "        function(value) {\n"
879                 + "          log(value);\n"
880                 + "        })\n"
881                 + "        log('done');\n"
882                 + "      }\n"
883                 + "    }\n"
884                 + "  </script>\n"
885                 + "</head>\n"
886                 + "<body onload='test()'>\n"
887                 + LOG_TEXTAREA
888                 + "</body>\n"
889                 + "</html>";
890 
891         loadPageVerifyTextArea2(html);
892     }
893 
894     /**
895      * @throws Exception if an error occurs
896      */
897     @Test
898     @Alerts({"done", "first", "second"})
899     public void thenAsyncPromiseAsyncResolved() throws Exception {
900         final String html = DOCTYPE_HTML
901                 + "<html>\n"
902                 + "<head>\n"
903                 + "  <script>\n"
904                 + LOG_TEXTAREA_FUNCTION
905                 + "    function test() {\n"
906                 + "      if (window.Promise) {\n"
907                 + "        var p = new Promise(function(resolve, reject) {\n"
908                 + "           window.setTimeout( function() {\n"
909                 + "             resolve('first');\n"
910                 + "           }, 20);\n"
911                 + "        })\n"
912                 + "        var p2 = p.then(function(value) {\n"
913                 + "          log(value);\n"
914                 + "          return new Promise(function(resolve, reject) {\n"
915                 + "             window.setTimeout( function() {\n"
916                 + "               resolve('second');\n"
917                 + "             }, 20);\n"
918                 + "          })\n"
919                 + "        })\n"
920                 + "        p2.then(function(value) {\n"
921                 + "          log(value);\n"
922                 + "        })\n"
923                 + "        log('done');\n"
924                 + "      }\n"
925                 + "    }\n"
926                 + "  </script>\n"
927                 + "</head>\n"
928                 + "<body onload='test()'>\n"
929                 + LOG_TEXTAREA
930                 + "</body>\n"
931                 + "</html>";
932 
933         loadPageVerifyTextArea2(html);
934     }
935 
936     /**
937      * @throws Exception if an error occurs
938      */
939     @Test
940     @Alerts({"done", "first", "second"})
941     public void thenAsyncPromiseAsyncRejected() throws Exception {
942         final String html = DOCTYPE_HTML
943                 + "<html>\n"
944                 + "<head>\n"
945                 + "  <script>\n"
946                 + LOG_TEXTAREA_FUNCTION
947                 + "    function test() {\n"
948                 + "      if (window.Promise) {\n"
949                 + "        var p = new Promise(function(resolve, reject) {\n"
950                 + "           window.setTimeout( function() {\n"
951                 + "             resolve('first');\n"
952                 + "           }, 20);\n"
953                 + "        })\n"
954                 + "        var p2 = p.then(function(value) {\n"
955                 + "          log(value);\n"
956                 + "          return new Promise(function(resolve, reject) {\n"
957                 + "             window.setTimeout( function() {\n"
958                 + "               reject('second');\n"
959                 + "             }, 20);\n"
960                 + "          })\n"
961                 + "        })\n"
962                 + "        p2.then(function(value) {\n"
963                 + "          log('Failure');\n"
964                 + "        },"
965                 + "        function(value) {\n"
966                 + "          log(value);\n"
967                 + "        })\n"
968                 + "        log('done');\n"
969                 + "      }\n"
970                 + "    }\n"
971                 + "  </script>\n"
972                 + "</head>\n"
973                 + "<body onload='test()'>\n"
974                 + LOG_TEXTAREA
975                 + "</body>\n"
976                 + "</html>";
977 
978         loadPageVerifyTextArea2(html);
979     }
980 
981     /**
982      * @throws Exception if an error occurs
983      */
984     @Test
985     @Alerts({"done", "Success first"})
986     public void thenTestAsyncChainedResolve() throws Exception {
987         final String html = DOCTYPE_HTML
988                 + "<html>\n"
989                 + "<head>\n"
990                 + "  <script>\n"
991                 + LOG_TEXTAREA_FUNCTION
992                 + "    function test() {\n"
993                 + "      if (window.Promise) {\n"
994                 + "        var p = new Promise(function(resolve, reject) {\n"
995                 + "           window.setTimeout( function() {\n"
996                 + "             resolve('first');\n"
997                 + "           }, 20);\n"
998                 + "        })\n"
999                 + "        var p2 = p.then(undefined, function(value) {\n"
1000                 + "          log(value);\n"
1001                 + "        })\n"
1002                 + "        p2.then(function(value) {\n"
1003                 + "          log('Success ' + value);\n"
1004                 + "        },"
1005                 + "        function(value) {\n"
1006                 + "          log('Failure ' + value);\n"
1007                 + "        })\n"
1008                 + "        log('done');\n"
1009                 + "      }\n"
1010                 + "    }\n"
1011                 + "  </script>\n"
1012                 + "</head>\n"
1013                 + "<body onload='test()'>\n"
1014                 + LOG_TEXTAREA
1015                 + "</body>\n"
1016                 + "</html>";
1017 
1018         loadPageVerifyTextArea2(html);
1019     }
1020 
1021     /**
1022      * @throws Exception if an error occurs
1023      */
1024     @Test
1025     @Alerts({"done", "Failure first"})
1026     public void thenTestAsyncChainedReject() throws Exception {
1027         final String html = DOCTYPE_HTML
1028                 + "<html>\n"
1029                 + "<head>\n"
1030                 + "  <script>\n"
1031                 + LOG_TEXTAREA_FUNCTION
1032                 + "    function test() {\n"
1033                 + "      if (window.Promise) {\n"
1034                 + "        var p = new Promise(function(resolve, reject) {\n"
1035                 + "           window.setTimeout( function() {\n"
1036                 + "             reject('first');\n"
1037                 + "           }, 20);\n"
1038                 + "        })\n"
1039                 + "        var p2 = p.then(function(value) {\n"
1040                 + "          log(value);\n"
1041                 + "        }, undefined)\n"
1042                 + "        p2.then(function(value) {\n"
1043                 + "          log('Success ' + value);\n"
1044                 + "        },"
1045                 + "        function(value) {\n"
1046                 + "          log('Failure ' + value);\n"
1047                 + "        })\n"
1048                 + "        log('done');\n"
1049                 + "      }\n"
1050                 + "    }\n"
1051                 + "  </script>\n"
1052                 + "</head>\n"
1053                 + "<body onload='test()'>\n"
1054                 + LOG_TEXTAREA
1055                 + "</body>\n"
1056                 + "</html>";
1057 
1058         loadPageVerifyTextArea2(html);
1059     }
1060 
1061     /**
1062      * @throws Exception if an error occurs
1063      */
1064     @Test
1065     @Alerts({"done", "Success first"})
1066     public void thenTestAsyncChainedNotAFunction() throws Exception {
1067         final String html = DOCTYPE_HTML
1068                 + "<html>\n"
1069                 + "<head>\n"
1070                 + "  <script>\n"
1071                 + LOG_TEXTAREA_FUNCTION
1072                 + "    function test() {\n"
1073                 + "      if (window.Promise) {\n"
1074                 + "        var p = new Promise(function(resolve, reject) {\n"
1075                 + "           window.setTimeout( function() {\n"
1076                 + "             resolve('first');\n"
1077                 + "           }, 20);\n"
1078                 + "        })\n"
1079                 + "        var p2 = p.then(7);\n"
1080                 + "        var p3 = p2.then('test');\n"
1081                 + "        p3.then(function(value) {\n"
1082                 + "          log('Success ' + value);\n"
1083                 + "        },"
1084                 + "        function(value) {\n"
1085                 + "          log('Failure ' + value);\n"
1086                 + "        })\n"
1087                 + "        log('done');\n"
1088                 + "      }\n"
1089                 + "    }\n"
1090                 + "  </script>\n"
1091                 + "</head>\n"
1092                 + "<body onload='test()'>\n"
1093                 + LOG_TEXTAREA
1094                 + "</body>\n"
1095                 + "</html>";
1096 
1097         loadPageVerifyTextArea2(html);
1098     }
1099 
1100     /**
1101      * @throws Exception if an error occurs
1102      */
1103     @Test
1104     @Alerts({"Success", "string", "oh, no!", "after catch"})
1105     public void catchTest() throws Exception {
1106         final String html = DOCTYPE_HTML
1107                 + "<html>\n"
1108                 + "<head>\n"
1109                 + "  <script>\n"
1110                 + LOG_TEXTAREA_FUNCTION
1111                 + "    function test() {\n"
1112                 + "      if (window.Promise) {\n"
1113                 + "        var p = new Promise(function(resolve, reject) {\n"
1114                 + "          resolve('Success');\n"
1115                 + "        });\n"
1116                 + "\n"
1117                 + "        p.then(function(value) {\n"
1118                 + "          log(value);\n"
1119                 + "          throw 'oh, no!';\n"
1120                 + "        }).catch(function(e) {\n"
1121                 + "          log(typeof e);\n"
1122                 + "          log(e);\n"
1123                 + "        }).then(function(e) {\n"
1124                 + "          log('after catch');\n"
1125                 + "        }, function() {\n"
1126                 + "          log('failure');\n"
1127                 + "        });\n"
1128                 + "      }\n"
1129                 + "    }\n"
1130                 + "  </script>\n"
1131                 + "</head>\n"
1132                 + "<body onload='test()'>\n"
1133                 + LOG_TEXTAREA
1134                 + "</body>\n"
1135                 + "</html>";
1136 
1137         loadPageVerifyTextArea2(html);
1138     }
1139 
1140     /**
1141      * @throws Exception if an error occurs
1142      */
1143     @Test
1144     @Alerts({"Success", "string", "oh, no!", "after catch"})
1145     public void catchTestAsync() throws Exception {
1146         final String html = DOCTYPE_HTML
1147                 + "<html>\n"
1148                 + "<head>\n"
1149                 + "  <script>\n"
1150                 + LOG_TEXTAREA_FUNCTION
1151                 + "    function test() {\n"
1152                 + "      if (window.Promise) {\n"
1153                 + "        var p = new Promise(function(resolve, reject) {\n"
1154                 + "           window.setTimeout( function() {\n"
1155                 + "             resolve('Success');\n"
1156                 + "           }, 20);\n"
1157                 + "        })\n"
1158                 + "        p.then(function(value) {\n"
1159                 + "          log(value);\n"
1160                 + "          throw 'oh, no!';\n"
1161                 + "        }).catch(function(e) {\n"
1162                 + "          log(typeof e);\n"
1163                 + "          log(e);\n"
1164                 + "        }).then(function(e) {\n"
1165                 + "          log('after catch');\n"
1166                 + "        }, function() {\n"
1167                 + "          log('failure');\n"
1168                 + "        });\n"
1169                 + "      }\n"
1170                 + "    }\n"
1171                 + "  </script>\n"
1172                 + "</head>\n"
1173                 + "<body onload='test()'>\n"
1174                 + LOG_TEXTAREA
1175                 + "</body>\n"
1176                 + "</html>";
1177 
1178         loadPageVerifyTextArea2(html);
1179     }
1180 
1181     /**
1182      * @throws Exception if an error occurs
1183      */
1184     @Test
1185     @Alerts({"done", "Success first"})
1186     public void catchTestAsyncChained() throws Exception {
1187         final String html = DOCTYPE_HTML
1188                 + "<html>\n"
1189                 + "<head>\n"
1190                 + "  <script>\n"
1191                 + LOG_TEXTAREA_FUNCTION
1192                 + "    function test() {\n"
1193                 + "      if (window.Promise) {\n"
1194                 + "        var p = new Promise(function(resolve, reject) {\n"
1195                 + "           window.setTimeout( function() {\n"
1196                 + "             resolve('first');\n"
1197                 + "           }, 20);\n"
1198                 + "        })\n"
1199                 + "        var p2 = p.catch(function(value) {\n"
1200                 + "          log(value);\n"
1201                 + "        })\n"
1202                 + "        p2.then(function(value) {\n"
1203                 + "          log('Success ' + value);\n"
1204                 + "        },"
1205                 + "        function(value) {\n"
1206                 + "          log('Failure ' + value);\n"
1207                 + "        })\n"
1208                 + "        log('done');\n"
1209                 + "      }\n"
1210                 + "    }\n"
1211                 + "  </script>\n"
1212                 + "</head>\n"
1213                 + "<body onload='test()'>\n"
1214                 + LOG_TEXTAREA
1215                 + "</body>\n"
1216                 + "</html>";
1217 
1218         loadPageVerifyTextArea2(html);
1219     }
1220 
1221     /**
1222      * @throws Exception if an error occurs
1223      */
1224     @Test
1225     @Alerts({"done", "Success"})
1226     public void thenInsideEventHandler() throws Exception {
1227         final String html = DOCTYPE_HTML
1228                 + "<html>\n"
1229                 + "<head>\n"
1230                 + "  <script>\n"
1231                 + LOG_TEXTAREA_FUNCTION
1232                 + "    function test() {\n"
1233                 + "      if (window.Promise) {\n"
1234                 + "        document.getElementById('btn1').onclick = function() {\n"
1235                 + "          new Promise(function(resolve, reject) {\n"
1236                 + "            window.setTimeout( function() {\n"
1237                 + "              resolve('Success');\n"
1238                 + "            }, 20);\n"
1239                 + "          }).then(function(value) {\n"
1240                 + "            log(value);\n"
1241                 + "          });\n"
1242                 + "          log('done');\n"
1243                 + "        };\n"
1244                 + "      }\n"
1245                 + "    }\n"
1246                 + "  </script>\n"
1247                 + "</head>\n"
1248                 + "<body onload='test()'>\n"
1249                 + "  <button id='btn1'>BTN1</button>\n"
1250                 + LOG_TEXTAREA
1251                 + "</body>\n"
1252                 + "</html>\n";
1253 
1254         final WebDriver driver = loadPage2(html);
1255         driver.findElement(By.id("btn1")).click();
1256 
1257         verifyTextArea2(driver, getExpectedAlerts());
1258     }
1259 
1260     /**
1261      * @throws Exception if an error occurs
1262      */
1263     @Test
1264     @Alerts({"create thenable 4", "fulfilled"})
1265     public void thenThenable() throws Exception {
1266         final String html = DOCTYPE_HTML
1267             + "<html>\n"
1268             + "<head>\n"
1269             + "  <script>\n"
1270             + LOG_TEXTAREA_FUNCTION
1271             + "    function test() {\n"
1272             + "      if (window.Promise) {\n"
1273 
1274             + "        var p1 = Promise.resolve(4);\n"
1275             + "        p2 = p1.then(function(v) {\n"
1276             + "          log('create thenable ' + v);\n"
1277             + "          return { then: function(onFulfill, onReject) { onFulfill('fulfilled'); }};\n"
1278             + "        });\n"
1279             + "\n"
1280             + "        p2.then(function(v) {\n"
1281             + "            log(v);\n"
1282             + "        }, function(e) {\n"
1283             + "            log('failure');\n"
1284             + "        });\n"
1285 
1286             + "      }\n"
1287             + "    }\n"
1288             + "  </script>\n"
1289             + "</head>\n"
1290             + "<body onload='test()'>\n"
1291             + LOG_TEXTAREA
1292             + "</body>\n"
1293             + "</html>";
1294 
1295         loadPageVerifyTextArea2(html);
1296     }
1297 
1298     /**
1299      * @throws Exception if an error occurs
1300      */
1301     @Test
1302     @Alerts("failure1")
1303     public void thenThenableThrows() throws Exception {
1304         final String html = DOCTYPE_HTML
1305             + "<html>\n"
1306             + "<head>\n"
1307             + "  <script>\n"
1308             + LOG_TEXTAREA_FUNCTION
1309             + "    function test() {\n"
1310             + "      if (window.Promise) {\n"
1311 
1312             + "        var thenable = {\n"
1313             + "          then: function(resolve) {\n"
1314             + "            throw new TypeError('Throwing 1');\n"
1315             + "            resolve(\"Resolving\");\n"
1316             + "          }\n"
1317             + "        };\n"
1318             + "\n"
1319             + "        var p1 = Promise.resolve(1);\n"
1320             + "        p2 = p1.then(thenable);\n"
1321 
1322             + "        p2.then(function(v) {\n"
1323             + "          log('failure' + v);\n"
1324             + "        }, function(e) {\n"
1325             + "          log(e);\n"
1326             + "        });\n"
1327 
1328             + "      }\n"
1329             + "    }\n"
1330             + "  </script>\n"
1331             + "</head>\n"
1332             + "<body onload='test()'>\n"
1333             + LOG_TEXTAREA
1334             + "</body>\n"
1335             + "</html>";
1336 
1337         loadPageVerifyTextArea2(html);
1338     }
1339 
1340     /**
1341      * @throws Exception if an error occurs
1342      */
1343     @Test
1344     @Alerts({"done", "failure1"})
1345     public void thenNotThenable() throws Exception {
1346         final String html = DOCTYPE_HTML
1347             + "<html>\n"
1348             + "<head>\n"
1349             + "  <script>\n"
1350             + LOG_TEXTAREA_FUNCTION
1351             + "    function test() {\n"
1352             + "      if (window.Promise) {\n"
1353 
1354             + "        var elseable = {\n"
1355             + "          else: function(resolve) {\n"
1356             + "            resolve(\"Resolving\");\n"
1357             + "          }\n"
1358             + "        };\n"
1359             + "\n"
1360             + "        var p1 = Promise.resolve(1);\n"
1361             + "        try{\n"
1362             + "          p2 = p1.then(elseable);\n"
1363             + "          log('done');\n"
1364             + "        } catch(e) { log(e instanceof TypeError); }\n"
1365 
1366             + "        p2.then(function(v) {\n"
1367             + "          log('failure' + v);\n"
1368             + "        }, function(e) {\n"
1369             + "          log(e);\n"
1370             + "        });\n"
1371 
1372             + "      }\n"
1373             + "    }\n"
1374             + "  </script>\n"
1375             + "</head>\n"
1376             + "<body onload='test()'>\n"
1377             + LOG_TEXTAREA
1378             + "</body>\n"
1379             + "</html>";
1380 
1381         loadPageVerifyTextArea2(html);
1382     }
1383 
1384     /**
1385      * @throws Exception if an error occurs
1386      */
1387     @Test
1388     @Alerts("1")
1389     public void thenThenableThrowsAfterCallback() throws Exception {
1390         final String html = DOCTYPE_HTML
1391             + "<html>\n"
1392             + "<head>\n"
1393             + "  <script>\n"
1394             + LOG_TEXTAREA_FUNCTION
1395             + "    function test() {\n"
1396             + "      if (window.Promise) {\n"
1397 
1398             + "        var thenable = {\n"
1399             + "          then: function(resolve) {\n"
1400             + "            resolve('Resolving');\n"
1401             + "            throw new TypeError('Throwing 2');\n"
1402             + "          }\n"
1403             + "        };\n"
1404             + "\n"
1405             + "        var p1 = Promise.resolve(1);\n"
1406             + "        p2 = p1.then(thenable);\n"
1407 
1408             + "        p2.then(function(v) {\n"
1409             + "          log(v);\n"
1410             + "        }, function(e) {\n"
1411             + "          log('failure');\n"
1412             + "        });\n"
1413             + "      }\n"
1414             + "    }\n"
1415             + "  </script>\n"
1416             + "</head>\n"
1417             + "<body onload='test()'>\n"
1418             + LOG_TEXTAREA
1419             + "</body>\n"
1420             + "</html>";
1421 
1422         loadPageVerifyTextArea2(html);
1423     }
1424 
1425     /**
1426      * @throws Exception if an error occurs
1427      */
1428     @Test
1429     @Alerts({"done", "object", "3", "3,1337,Success"})
1430     public void allAsyncArray() throws Exception {
1431         final String html = DOCTYPE_HTML
1432             + "<html>\n"
1433             + "<head>\n"
1434             + "  <script>\n"
1435             + LOG_TEXTAREA_FUNCTION
1436             + "    function test() {\n"
1437             + "      if (window.Promise) {\n"
1438             + "        var p1 = Promise.resolve(3);\n"
1439             + "        var p2 = 1337;\n"
1440             + "        var p3 = new Promise(function(resolve, reject) {\n"
1441             + "            window.setTimeout( function() {\n"
1442             + "              resolve('Success');\n"
1443             + "            }, 20);\n"
1444             + "        });\n"
1445             + "\n"
1446             + "        Promise.all([p1, p2, p3]).then(function(values) {\n"
1447             + "          log(typeof values);\n"
1448             + "          log(values.length);\n"
1449             + "          log(values);\n"
1450             + "        });\n"
1451             + "        log('done');\n"
1452             + "      }\n"
1453             + "    }\n"
1454             + "</script></head>\n"
1455             + "<body onload='test()'>\n"
1456             + LOG_TEXTAREA
1457             + "</body>\n"
1458             + "</html>\n";
1459 
1460         loadPageVerifyTextArea2(html);
1461     }
1462 
1463     /**
1464      * @throws Exception if an error occurs
1465      */
1466     @Test
1467     @Alerts({"done", "first 3,1337,Success", "second 3,Success"})
1468     public void allAsyncArray2() throws Exception {
1469         final String html = DOCTYPE_HTML
1470             + "<html>\n"
1471             + "<head>\n"
1472             + "  <script>\n"
1473             + LOG_TEXTAREA_FUNCTION
1474             + "    function test() {\n"
1475             + "      if (window.Promise) {\n"
1476             + "        var p1 = Promise.resolve(3);\n"
1477             + "        var p2 = 1337;\n"
1478             + "        var p3 = new Promise(function(resolve, reject) {\n"
1479             + "            window.setTimeout( function() {\n"
1480             + "              resolve('Success');\n"
1481             + "            }, 20);\n"
1482             + "        });\n"
1483             + "\n"
1484             + "        Promise.all([p1, p2, p3]).then(function(values) {\n"
1485             + "          log('first ' + values);\n"
1486             + "        });\n"
1487             + "        Promise.all([p1, p3]).then(function(values) {\n"
1488             + "          log('second ' + values);\n"
1489             + "        });\n"
1490             + "        log('done');\n"
1491             + "      }\n"
1492             + "    }\n"
1493             + "</script></head>\n"
1494             + "<body onload='test()'>\n"
1495             + LOG_TEXTAREA
1496             + "</body>\n"
1497             + "</html>\n";
1498 
1499         loadPageVerifyTextArea2(html);
1500     }
1501 
1502     /**
1503      * @throws Exception if an error occurs
1504      */
1505     @Test
1506     @Alerts({"done", "object", "3", "3,1337,Success"})
1507     public void allAsyncSet() throws Exception {
1508         final String html = DOCTYPE_HTML
1509             + "<html>\n"
1510             + "<head>\n"
1511             + "  <script>\n"
1512             + LOG_TEXTAREA_FUNCTION
1513             + "    function test() {\n"
1514             + "      if (window.Promise) {\n"
1515             + "        var p1 = Promise.resolve(3);\n"
1516             + "        var p2 = 1337;\n"
1517             + "        var p3 = new Promise(function(resolve, reject) {\n"
1518             + "            window.setTimeout( function() {\n"
1519             + "              resolve('Success');\n"
1520             + "            }, 20);\n"
1521             + "        });\n"
1522             + "\n"
1523             + "        Promise.all(new Set([p1, p2, p3])).then(function(values) {\n"
1524             + "          log(typeof values);\n"
1525             + "          log(values.length);\n"
1526             + "          log(values);\n"
1527             + "        });\n"
1528             + "        log('done');\n"
1529             + "      }\n"
1530             + "    }\n"
1531             + "</script></head>\n"
1532             + "<body onload='test()'>\n"
1533             + LOG_TEXTAREA
1534             + "</body>\n"
1535             + "</html>\n";
1536 
1537         loadPageVerifyTextArea2(html);
1538     }
1539 
1540     /**
1541      * @throws Exception if an error occurs
1542      */
1543     @Test
1544     @Alerts({"done", "string", "Failed"})
1545     public void allRejectAsync() throws Exception {
1546         final String html = DOCTYPE_HTML
1547             + "<html>\n"
1548             + "<head>\n"
1549             + "  <script>\n"
1550             + LOG_TEXTAREA_FUNCTION
1551             + "    function test() {\n"
1552             + "      if (window.Promise) {\n"
1553             + "        var p1 = Promise.resolve(3);\n"
1554             + "        var p2 = 1337;\n"
1555             + "        var p3 = new Promise(function(resolve, reject) {\n"
1556             + "            window.setTimeout( function() {\n"
1557             + "              reject('Failed');\n"
1558             + "            }, 20);\n"
1559             + "        });\n"
1560             + "\n"
1561             + "        Promise.all([p1, p2, p3]).then(function(value) {\n"
1562             + "            log('failure');\n"
1563             + "        }, function(value) {\n"
1564             + "          log(typeof value);\n"
1565             + "          log(value);\n"
1566             + "        });\n"
1567             + "        log('done');\n"
1568             + "      }\n"
1569             + "    }\n"
1570             + "</script></head>\n"
1571             + "<body onload='test()'>\n"
1572             + LOG_TEXTAREA
1573             + "</body>\n"
1574             + "</html>\n";
1575 
1576         loadPageVerifyTextArea2(html);
1577     }
1578 
1579     /**
1580      * @throws Exception if an error occurs
1581      */
1582     @Test
1583     @Alerts({"done", "first Failed", "second Failed"})
1584     public void allRejectAsync2() throws Exception {
1585         final String html = DOCTYPE_HTML
1586             + "<html>\n"
1587             + "<head>\n"
1588             + "  <script>\n"
1589             + LOG_TEXTAREA_FUNCTION
1590             + "    function test() {\n"
1591             + "      if (window.Promise) {\n"
1592             + "        var p1 = Promise.resolve(3);\n"
1593             + "        var p2 = 1337;\n"
1594             + "        var p3 = new Promise(function(resolve, reject) {\n"
1595             + "            window.setTimeout( function() {\n"
1596             + "              reject('Failed');\n"
1597             + "            }, 20);\n"
1598             + "        });\n"
1599             + "\n"
1600             + "        Promise.all([p1, p2, p3]).then(function(value) {\n"
1601             + "            log('failure');\n"
1602             + "        }, function(value) {\n"
1603             + "          log('first ' + value);\n"
1604             + "        });\n"
1605             + "        Promise.all([p1, p3]).then(function(value) {\n"
1606             + "            log('failure');\n"
1607             + "        }, function(value) {\n"
1608             + "          log('second ' + value);\n"
1609             + "        });\n"
1610             + "        log('done');\n"
1611             + "      }\n"
1612             + "    }\n"
1613             + "</script></head>\n"
1614             + "<body onload='test()'>\n"
1615             + LOG_TEXTAREA
1616             + "</body>\n"
1617             + "</html>\n";
1618 
1619         loadPageVerifyTextArea2(html);
1620     }
1621 
1622     /**
1623      * @throws Exception if an error occurs
1624      */
1625     @Test
1626     @Alerts({"done", "Success 2"})
1627     public void raceAsync() throws Exception {
1628         final String html = DOCTYPE_HTML
1629             + "<html>\n"
1630             + "<head>\n"
1631             + "  <script>\n"
1632             + LOG_TEXTAREA_FUNCTION
1633             + "    function test() {\n"
1634             + "      if (window.Promise) {\n"
1635             + "        var p1 = new Promise(function(resolve, reject) {\n"
1636             + "            window.setTimeout( function() {\n"
1637             + "              resolve('Success');\n"
1638             + "            }, 40);\n"
1639             + "        });\n"
1640             + "        var p2 = new Promise(function(resolve, reject) {\n"
1641             + "            window.setTimeout( function() {\n"
1642             + "              resolve('Success 2');\n"
1643             + "            }, 20);\n"
1644             + "        });\n"
1645             + "\n"
1646             + "        Promise.race([p1, p2]).then(function(value) {\n"
1647             + "          log(value);\n"
1648             + "        }, function(value) {\n"
1649             + "          log('failure');\n"
1650             + "        });\n"
1651             + "        log('done');\n"
1652             + "      }\n"
1653             + "    }\n"
1654             + "</script></head>\n"
1655             + "<body onload='test()'>\n"
1656             + LOG_TEXTAREA
1657             + "</body>\n"
1658             + "</html>\n";
1659 
1660         loadPageVerifyTextArea2(html);
1661     }
1662 
1663     /**
1664      * @throws Exception if an error occurs
1665      */
1666     @Test
1667     @Alerts({"done", "first Success 2", "second Success 2"})
1668     public void raceAsync2() throws Exception {
1669         final String html = DOCTYPE_HTML
1670             + "<html>\n"
1671             + "<head>\n"
1672             + "  <script>\n"
1673             + LOG_TEXTAREA_FUNCTION
1674             + "    function test() {\n"
1675             + "      if (window.Promise) {\n"
1676             + "        var p1 = new Promise(function(resolve, reject) {\n"
1677             + "            window.setTimeout( function() {\n"
1678             + "              resolve('Success');\n"
1679             + "            }, 40);\n"
1680             + "        });\n"
1681             + "        var p2 = new Promise(function(resolve, reject) {\n"
1682             + "            window.setTimeout( function() {\n"
1683             + "              resolve('Success 2');\n"
1684             + "            }, 20);\n"
1685             + "        });\n"
1686             + "\n"
1687             + "        Promise.race([p1, p2]).then(function(value) {\n"
1688             + "          log('first ' + value);\n"
1689             + "        }, function(value) {\n"
1690             + "          log('failure');\n"
1691             + "        });\n"
1692             + "        Promise.race([p1, p2]).then(function(value) {\n"
1693             + "          log('second ' + value);\n"
1694             + "        }, function(value) {\n"
1695             + "          log('failure');\n"
1696             + "        });\n"
1697             + "        log('done');\n"
1698             + "      }\n"
1699             + "    }\n"
1700             + "</script></head>\n"
1701             + "<body onload='test()'>\n"
1702             + LOG_TEXTAREA
1703             + "</body>\n"
1704             + "</html>\n";
1705 
1706         loadPageVerifyTextArea2(html);
1707     }
1708 
1709     /**
1710      * @throws Exception if an error occurs
1711      */
1712     @Test
1713     @Alerts({"done", "Failed"})
1714     public void raceRejectAsync() throws Exception {
1715         final String html = DOCTYPE_HTML
1716             + "<html>\n"
1717             + "<head>\n"
1718             + "  <script>\n"
1719             + LOG_TEXTAREA_FUNCTION
1720             + "    function test() {\n"
1721             + "      if (window.Promise) {\n"
1722             + "        var p1 = new Promise(function(resolve, reject) {\n"
1723             + "            window.setTimeout( function() {\n"
1724             + "              resolve('Success');\n"
1725             + "            }, 40);\n"
1726             + "        });\n"
1727             + "        var p2 = new Promise(function(resolve, reject) {\n"
1728             + "            window.setTimeout( function() {\n"
1729             + "              reject('Failed');\n"
1730             + "            }, 20);\n"
1731             + "        });\n"
1732             + "\n"
1733             + "        Promise.race([p1, p2]).then(function(value) {\n"
1734             + "          log('failure');\n"
1735             + "        }, function(value) {\n"
1736             + "          log(value);\n"
1737             + "        });\n"
1738             + "        log('done');\n"
1739             + "      }\n"
1740             + "    }\n"
1741             + "</script></head>\n"
1742             + "<body onload='test()'>\n"
1743             + LOG_TEXTAREA
1744             + "</body>\n"
1745             + "</html>\n";
1746 
1747         loadPageVerifyTextArea2(html);
1748     }
1749 
1750     /**
1751      * @throws Exception if an error occurs
1752      */
1753     @Test
1754     @Alerts({"done", "first Failed", "second Failed"})
1755     public void raceRejectAsync2() throws Exception {
1756         final String html = DOCTYPE_HTML
1757             + "<html>\n"
1758             + "<head>\n"
1759             + "  <script>\n"
1760             + LOG_TEXTAREA_FUNCTION
1761             + "    function test() {\n"
1762             + "      if (window.Promise) {\n"
1763             + "        var p1 = new Promise(function(resolve, reject) {\n"
1764             + "            window.setTimeout( function() {\n"
1765             + "              resolve('Success');\n"
1766             + "            }, 40);\n"
1767             + "        });\n"
1768             + "        var p2 = new Promise(function(resolve, reject) {\n"
1769             + "            window.setTimeout( function() {\n"
1770             + "              reject('Failed');\n"
1771             + "            }, 20);\n"
1772             + "        });\n"
1773             + "\n"
1774             + "        Promise.race([p1, p2]).then(function(value) {\n"
1775             + "          log('failure');\n"
1776             + "        }, function(value) {\n"
1777             + "          log('first ' + value);\n"
1778             + "        });\n"
1779             + "        Promise.race([p1, p2]).then(function(value) {\n"
1780             + "          log('failure');\n"
1781             + "        }, function(value) {\n"
1782             + "          log('second ' + value);\n"
1783             + "        });\n"
1784             + "        log('done');\n"
1785             + "      }\n"
1786             + "    }\n"
1787             + "</script></head>\n"
1788             + "<body onload='test()'>\n"
1789             + LOG_TEXTAREA
1790             + "</body>\n"
1791             + "</html>\n";
1792 
1793         loadPageVerifyTextArea2(html);
1794     }
1795 
1796     /**
1797      * @throws Exception if the test fails
1798      */
1799     @Test
1800     @Alerts("")
1801     public void changeLocationFromPromise() throws Exception {
1802         final String html = DOCTYPE_HTML
1803               + "<html>\n"
1804               + "<head>\n"
1805               + "  <title>test</title>\n"
1806               + "  <script>\n"
1807               + "    function test() {\n"
1808               + "      if (window.Promise) {\n"
1809               + "        Promise.resolve(1).then(function () {\n"
1810               + "          location.href = 'about:blank';\n"
1811               + "        });\n"
1812               + "      }\n"
1813               + "    }\n"
1814               + "  </script>\n"
1815               + "</head>\n"
1816               + "<body onload='test()'>\n"
1817               + "</body>\n"
1818               + "</html>";
1819 
1820         final WebDriver driver = loadPage2(html);
1821         Thread.sleep(100);
1822         assertTitle(driver, getExpectedAlerts()[0]);
1823     }
1824 
1825     /**
1826      * @throws Exception if the test fails
1827      */
1828     @Test
1829     @Alerts(DEFAULT = {"function\\sPromise()\\s{\\s[native\\scode]\\s}", "true", "[GC]"},
1830             FF = {"function\\sPromise()\\s{\\n\\s\\s\\s\\s[native\\scode]\\n}", "true", "[GC]"},
1831             FF_ESR = {"function\\sPromise()\\s{\\n\\s\\s\\s\\s[native\\scode]\\n}", "true", "[GC]"})
1832     public void speciesValue() throws Exception {
1833         final String html = DOCTYPE_HTML
1834               + "<html>\n"
1835               + "<head>\n"
1836               + "  <script>\n"
1837               + LOG_TITLE_FUNCTION_NORMALIZE
1838               + "    function test() {\n"
1839               + "      if (window.Promise) {\n"
1840               + "        log(Promise[Symbol.species]);\n"
1841               + "        log(Promise === Promise[Symbol.species]);\n"
1842 
1843               + "        let desc = Object.getOwnPropertyDescriptor(Promise, Symbol.species);\n"
1844               + "        let props = '[';\n"
1845               + "        if (desc.get != undefined) props += 'G';\n"
1846               + "        if (desc.set != undefined) props += 'S';\n"
1847               + "        if (desc.writable) props += 'W';\n"
1848               + "        if (desc.configurable) props += 'C';\n"
1849               + "        if (desc.enumerable) props += 'E';\n"
1850               + "        props += ']';\n"
1851               + "        log(props);\n"
1852               + "      }\n"
1853               + "    }\n"
1854               + "  </script>\n"
1855               + "</head>\n"
1856               + "<body onload='test()'>\n"
1857               + "</body>\n"
1858               + "</html>";
1859 
1860         loadPageVerifyTitle2(html);
1861     }
1862 }