Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / LayoutTests / http / tests / dom / resources / promise-rejection-events.js
blob8c1555588ae4e1d7c0c84647d32ecdd92e118744
1 'use strict';
3 if (self.importScripts) {
4   if ('ServiceWorkerGlobalScope' in self && self instanceof ServiceWorkerGlobalScope) {
5     importScripts('../../serviceworker/resources/worker-testharness.js');
6   } else {
7     importScripts('../../resources/testharness.js');
8   }
12 // Straightforward unhandledrejection tests
14 async_test(function(t) {
15   var e = new Error();
16   var p;
18   onUnhandledSucceed(t, e, function() { return p; });
20   p = Promise.reject(e);
21 }, 'unhandledrejection: from Promise.reject');
23 async_test(function(t) {
24   var e = new Error();
25   var p;
27   onUnhandledSucceed(t, e, function() { return p; });
29   p = new Promise(function(_, reject) {
30     reject(e);
31   });
32 }, 'unhandledrejection: from a synchronous rejection in new Promise');
34 async_test(function(t) {
35   var e = new Error();
36   var p;
38   onUnhandledSucceed(t, e, function() { return p; });
40   p = new Promise(function(_, reject) {
41     postMessageTask(function() {
42       reject(e);
43     });
44   });
45 }, 'unhandledrejection: from a task-delayed rejection');
47 async_test(function(t) {
48   var e = new Error();
49   var p;
51   onUnhandledSucceed(t, e, function() { return p; });
53   p = new Promise(function(_, reject) {
54     setTimeout(function() {
55       reject(e);
56     }, 1);
57   });
58 }, 'unhandledrejection: from a setTimeout-delayed rejection');
60 async_test(function(t) {
61   var e = new Error();
62   var e2 = new Error();
63   var promise2;
65   onUnhandledSucceed(t, e2, function() { return promise2; });
67   var unreached = t.unreached_func('promise should not be fulfilled');
68   promise2 = Promise.reject(e).then(unreached, function(reason) {
69     t.step(function() {
70       assert_equals(reason, e);
71     });
72     throw e2;
73   });
74 }, 'unhandledrejection: from a throw in a rejection handler chained off of Promise.reject');
76 async_test(function(t) {
77   var e = new Error();
78   var e2 = new Error();
79   var promise2;
81   onUnhandledSucceed(t, e2, function() { return promise2; });
83   var unreached = t.unreached_func('promise should not be fulfilled');
84   promise2 = new Promise(function(_, reject) {
85     setTimeout(function() {
86       reject(e);
87     }, 1);
88   }).then(unreached, function(reason) {
89     t.step(function() {
90       assert_equals(reason, e);
91     });
92     throw e2;
93   });
94 }, 'unhandledrejection: from a throw in a rejection handler chained off of a setTimeout-delayed rejection');
96 async_test(function(t) {
97   var e = new Error();
98   var e2 = new Error();
99   var promise2;
101   onUnhandledSucceed(t, e2, function() { return promise2; });
103   var promise = new Promise(function(_, reject) {
104     setTimeout(function() {
105       reject(e);
106       mutationObserverMicrotask(function() {
107         var unreached = t.unreached_func('promise should not be fulfilled');
108         promise2 = promise.then(unreached, function(reason) {
109           t.step(function() {
110             assert_equals(reason, e);
111           });
112           throw e2;
113         });
114       });
115     }, 1);
116   });
117 }, 'unhandledrejection: from a throw in a rejection handler attached one microtask after a setTimeout-delayed rejection');
119 async_test(function(t) {
120   var e = new Error();
121   var p;
123   onUnhandledSucceed(t, e, function() { return p; });
125   p = Promise.resolve().then(function() {
126     return Promise.reject(e);
127   });
128 }, 'unhandledrejection: from returning a Promise.reject-created rejection in a fulfillment handler');
130 async_test(function(t) {
131   var e = new Error();
132   var p;
134   onUnhandledSucceed(t, e, function() { return p; });
136   p = Promise.resolve().then(function() {
137     throw e;
138   });
139 }, 'unhandledrejection: from a throw in a fulfillment handler');
141 async_test(function(t) {
142   var e = new Error();
143   var p;
145   onUnhandledSucceed(t, e, function() { return p; });
147   p = Promise.resolve().then(function() {
148     return new Promise(function(_, reject) {
149       setTimeout(function() {
150         reject(e);
151       }, 1);
152     });
153   });
154 }, 'unhandledrejection: from returning a setTimeout-delayed rejection in a fulfillment handler');
156 async_test(function(t) {
157   var e = new Error();
158   var p;
160   onUnhandledSucceed(t, e, function() { return p; });
162   p = Promise.all([Promise.reject(e)]);
163 }, 'unhandledrejection: from Promise.reject, indirected through Promise.all');
166 // Negative unhandledrejection/rejectionhandled tests with immediate attachment
169 async_test(function(t) {
170   var e = new Error();
171   var p;
173   onUnhandledFail(t, function() { return p; });
175   var unreached = t.unreached_func('promise should not be fulfilled');
176   p = Promise.reject(e).then(unreached, function() {});
177 }, 'no unhandledrejection/rejectionhandled: rejection handler attached synchronously to a promise from Promise.reject');
179 async_test(function(t) {
180   var e = new Error();
181   var p;
183   onUnhandledFail(t, function() { return p; });
185   var unreached = t.unreached_func('promise should not be fulfilled');
186   p = Promise.all([Promise.reject(e)]).then(unreached, function() {});
187 }, 'no unhandledrejection/rejectionhandled: rejection handler attached synchronously to a promise from ' +
188    'Promise.reject, indirecting through Promise.all');
190 async_test(function(t) {
191   var e = new Error();
192   var p;
194   onUnhandledFail(t, function() { return p; });
196   var unreached = t.unreached_func('promise should not be fulfilled');
197   p = new Promise(function(_, reject) {
198     reject(e);
199   }).then(unreached, function() {});
200 }, 'no unhandledrejection/rejectionhandled: rejection handler attached synchronously to a synchronously-rejected ' +
201    'promise created with new Promise');
203 async_test(function(t) {
204   var e = new Error();
205   var p;
207   onUnhandledFail(t, function() { return p; });
209   var unreached = t.unreached_func('promise should not be fulfilled');
210   p = Promise.resolve().then(function() {
211     throw e;
212   }).then(unreached, function(reason) {
213     t.step(function() {
214       assert_equals(reason, e);
215     });
216   });
217 }, 'no unhandledrejection/rejectionhandled: rejection handler attached synchronously to a promise created from ' +
218    'throwing in a fulfillment handler');
220 async_test(function(t) {
221   var e = new Error();
222   var p;
224   onUnhandledFail(t, function() { return p; });
226   var unreached = t.unreached_func('promise should not be fulfilled');
227   p = Promise.resolve().then(function() {
228     return Promise.reject(e);
229   }).then(unreached, function(reason) {
230     t.step(function() {
231       assert_equals(reason, e);
232     });
233   });
234 }, 'no unhandledrejection/rejectionhandled: rejection handler attached synchronously to a promise created from ' +
235    'returning a Promise.reject-created promise in a fulfillment handler');
237 async_test(function(t) {
238   var e = new Error();
239   var p;
241   onUnhandledFail(t, function() { return p; });
243   var unreached = t.unreached_func('promise should not be fulfilled');
244   p = Promise.resolve().then(function() {
245     return new Promise(function(_, reject) {
246       setTimeout(function() {
247         reject(e);
248       }, 1);
249     });
250   }).then(unreached, function(reason) {
251     t.step(function() {
252       assert_equals(reason, e);
253     });
254   });
255 }, 'no unhandledrejection/rejectionhandled: rejection handler attached synchronously to a promise created from ' +
256    'returning a setTimeout-delayed rejection in a fulfillment handler');
258 async_test(function(t) {
259   var e = new Error();
260   var p;
262   onUnhandledFail(t, function() { return p; });
264   postMessageTask(function() {
265     p = Promise.resolve().then(function() {
266       return Promise.reject(e);
267     })
268     .catch(function() {});
269   });
270 }, 'no unhandledrejection/rejectionhandled: all inside a queued task, a rejection handler attached synchronously to ' +
271    'a promise created from returning a Promise.reject-created promise in a fulfillment handler');
274 // Negative unhandledrejection/rejectionhandled tests with delayed attachment
277 async_test(function(t) {
278   var e = new Error();
279   var p;
281   onUnhandledFail(t, function() { return p; });
283   p = Promise.reject(e);
284   mutationObserverMicrotask(function() {
285     var unreached = t.unreached_func('promise should not be fulfilled');
286     p.then(unreached, function() {});
287   });
288 }, 'delayed handling: a microtask delay before attaching a handler prevents both events (Promise.reject-created ' +
289    'promise)');
291 async_test(function(t) {
292   var e = new Error();
293   var p;
295   onUnhandledFail(t, function() { return p; });
297   p = new Promise(function(_, reject) {
298     reject(e);
299   });
300   mutationObserverMicrotask(function() {
301     var unreached = t.unreached_func('promise should not be fulfilled');
302     p.then(unreached, function() {});
303   });
304 }, 'delayed handling: a microtask delay before attaching a handler prevents both events (immediately-rejected new ' +
305    'Promise-created promise)');
307 async_test(function(t) {
308   var e = new Error();
309   var p1;
310   var p2;
312   onUnhandledFail(t, function() { return p1; });
313   onUnhandledFail(t, function() { return p2; });
315   p1 = new Promise(function(_, reject) {
316     mutationObserverMicrotask(function() {
317       reject(e);
318     });
319   });
320   p2 = Promise.all([p1]);
321   mutationObserverMicrotask(function() {
322     var unreached = t.unreached_func('promise should not be fulfilled');
323     p2.then(unreached, function() {});
324   });
325 }, 'delayed handling: a microtask delay before attaching the handler, and before rejecting the promise, indirected ' +
326    'through Promise.all');
329 // Negative unhandledrejection/rejectionhandled tests with nested-microtask-delayed attachment
332 async_test(function(t) {
333   var e = new Error();
334   var p;
336   onUnhandledFail(t, function() { return p; });
338   p = Promise.reject(e);
339   mutationObserverMicrotask(function() {
340     Promise.resolve().then(function() {
341       mutationObserverMicrotask(function() {
342         Promise.resolve().then(function() {
343           p.catch(function() {});
344         });
345       });
346     });
347   });
348 }, 'microtask nesting: attaching a handler inside a combination of mutationObserverMicrotask + promise microtasks');
350 async_test(function(t) {
351   var e = new Error();
352   var p;
354   onUnhandledFail(t, function() { return p; });
356   postMessageTask(function() {
357     p = Promise.reject(e);
358     mutationObserverMicrotask(function() {
359       Promise.resolve().then(function() {
360         mutationObserverMicrotask(function() {
361           Promise.resolve().then(function() {
362             p.catch(function() {});
363           });
364         });
365       });
366     });
367   });
368 }, 'microtask nesting: attaching a handler inside a combination of mutationObserverMicrotask + promise microtasks, ' +
369    'all inside a postMessageTask');
371 async_test(function(t) {
372   var e = new Error();
373   var p;
375   onUnhandledFail(t, function() { return p; });
377   setTimeout(function() {
378     p = Promise.reject(e);
379     mutationObserverMicrotask(function() {
380       Promise.resolve().then(function() {
381         mutationObserverMicrotask(function() {
382           Promise.resolve().then(function() {
383             p.catch(function() {});
384           });
385         });
386       });
387     });
388   }, 0);
389 }, 'microtask nesting: attaching a handler inside a combination of mutationObserverMicrotask + promise microtasks, ' +
390    'all inside a setTimeout');
392 async_test(function(t) {
393   var e = new Error();
394   var p;
396   onUnhandledFail(t, function() { return p; });
398   p = Promise.reject(e);
399   Promise.resolve().then(function() {
400     mutationObserverMicrotask(function() {
401       Promise.resolve().then(function() {
402         mutationObserverMicrotask(function() {
403           p.catch(function() {});
404         });
405       });
406     });
407   });
408 }, 'microtask nesting: attaching a handler inside a combination of promise microtasks + mutationObserverMicrotask');
410 async_test(function(t) {
411   var e = new Error();
412   var p;
414   onUnhandledFail(t, function() { return p; });
416   postMessageTask(function() {
417     p = Promise.reject(e);
418     Promise.resolve().then(function() {
419       mutationObserverMicrotask(function() {
420         Promise.resolve().then(function() {
421           mutationObserverMicrotask(function() {
422             p.catch(function() {});
423           });
424         });
425       });
426     });
427   });
428 }, 'microtask nesting: attaching a handler inside a combination of promise microtasks + mutationObserverMicrotask, ' +
429    'all inside a postMessageTask');
431 async_test(function(t) {
432   var e = new Error();
433   var p;
435   onUnhandledFail(t, function() { return p; });
437   setTimeout(function() {
438     p = Promise.reject(e);
439     Promise.resolve().then(function() {
440       mutationObserverMicrotask(function() {
441         Promise.resolve().then(function() {
442           mutationObserverMicrotask(function() {
443             p.catch(function() {});
444           });
445         });
446       });
447     });
448   }, 0);
449 }, 'microtask nesting: attaching a handler inside a combination of promise microtasks + mutationObserverMicrotask, ' +
450    'all inside a setTimeout');
453 // Positive unhandledrejection/rejectionhandled tests with delayed attachment
456 async_test(function(t) {
457   var e = new Error();
458   var p;
460   onUnhandledSucceed(t, e, function() { return p; });
462   var _reject;
463   p = new Promise(function(_, reject) {
464     _reject = reject;
465   });
466   _reject(e);
467   postMessageTask(function() {
468     var unreached = t.unreached_func('promise should not be fulfilled');
469     p.then(unreached, function() {});
470   });
471 }, 'delayed handling: a task delay before attaching a handler does not prevent unhandledrejection');
473 async_test(function(t) {
474   var unhandledPromises = [];
475   var unhandledReasons = [];
476   var e = new Error();
477   var p;
479   var unhandled = function(ev) {
480     if (ev.promise === p) {
481       t.step(function() {
482         unhandledPromises.push(ev.promise);
483         unhandledReasons.push(ev.reason);
484       });
485     }
486   };
487   var handled = function(ev) {
488     if (ev.promise === p) {
489       t.step(function() {
490         assert_array_equals(unhandledPromises, [p]);
491         assert_array_equals(unhandledReasons, [e]);
492         assert_equals(ev.promise, p);
493         assert_equals(ev.reason, e);
494       });
495     }
496   };
497   addEventListener('unhandledrejection', unhandled);
498   addEventListener('rejectionhandled', handled);
499   ensureCleanup(t, unhandled, handled);
501   p = new Promise(function() {
502     throw e;
503   });
504   setTimeout(function() {
505     var unreached = t.unreached_func('promise should not be fulfilled');
506     p.then(unreached, function(reason) {
507       assert_equals(reason, e);
508       setTimeout(function() { t.done(); }, 10);
509     });
510   }, 10);
511 }, 'delayed handling: delaying handling by setTimeout(,10) will cause both events to fire');
513 async_test(function(t) {
514   var e = new Error();
515   var p;
517   onUnhandledSucceed(t, e, function() { return p; });
519   p = Promise.reject(e);
520   postMessageTask(function() {
521     Promise.resolve().then(function() {
522       p.catch(function() {});
523     });
524   });
525 }, 'delayed handling: postMessageTask after promise creation/rejection, plus promise microtasks, is too late to ' +
526    'attach a rejection handler');
528 async_test(function(t) {
529   var e = new Error();
530   var p;
532   onUnhandledSucceed(t, e, function() { return p; });
533   postMessageTask(function() {
534     Promise.resolve().then(function() {
535       Promise.resolve().then(function() {
536         Promise.resolve().then(function() {
537           Promise.resolve().then(function() {
538             p.catch(function() {});
539           });
540         });
541       });
542     });
543   });
544   p = Promise.reject(e);
545 }, 'delayed handling: postMessageTask before promise creation/rejection, plus many promise microtasks, is too late ' +
546    'to attach a rejection handler');
548 async_test(function(t) {
549   var e = new Error();
550   var p;
552   onUnhandledSucceed(t, e, function() { return p; });
554   p = Promise.reject(e);
555   postMessageTask(function() {
556     Promise.resolve().then(function() {
557       Promise.resolve().then(function() {
558         Promise.resolve().then(function() {
559           Promise.resolve().then(function() {
560             p.catch(function() {});
561           });
562         });
563       });
564     });
565   });
566 }, 'delayed handling: postMessageTask after promise creation/rejection, plus many promise microtasks, is too late ' +
567    'to attach a rejection handler');
570 // Miscellaneous tests about integration with the rest of the platform
573 async_test(function(t) {
574   var e = new Error();
575   var l = function(ev) {
576     var order = [];
577     mutationObserverMicrotask(function() {
578       order.push(1);
579     });
580     setTimeout(function() {
581       order.push(2);
582       t.step(function() {
583         assert_array_equals(order, [1, 2]);
584       });
585       t.done();
586     }, 1);
587   };
588   addEventListener('unhandledrejection', l);
589   ensureCleanup(t, l);
590   Promise.reject(e);
591 }, 'mutationObserverMicrotask vs. postMessageTask ordering is not disturbed inside unhandledrejection events');
594 // HELPERS
597 function postMessageTask(f) {
598   if ('document' in self) {
599     var l = function() {
600       removeEventListener('message', l);
601       f();
602     };
603     addEventListener('message', l);
604     postMessage('abusingpostmessageforfunandprofit', '*');
605   } else {
606     var channel = new MessageChannel();
607     channel.port1.onmessage = function() { channel.port1.close(); f(); };
608     channel.port2.postMessage('abusingpostmessageforfunandprofit');
609     channel.port2.close();
610   }
613 function mutationObserverMicrotask(f) {
614   if ('document' in self) {
615     var observer = new MutationObserver(function() { f(); });
616     var node = document.createTextNode('');
617     observer.observe(node, { characterData: true });
618     node.data = 'foo';
619   } else {
620     // We don't have mutation observers on workers, so just post a promise-based
621     // microtask.
622     Promise.resolve().then(function() { f(); });
623   }
626 function onUnhandledSucceed(t, expectedReason, expectedPromiseGetter) {
627   var l = function(ev) {
628     if (ev.promise === expectedPromiseGetter()) {
629       t.step(function() {
630         assert_equals(ev.reason, expectedReason);
631         assert_equals(ev.promise, expectedPromiseGetter());
632       });
633       t.done();
634     }
635   };
636   addEventListener('unhandledrejection', l);
637   ensureCleanup(t, l);
640 function onUnhandledFail(t, expectedPromiseGetter) {
641   var unhandled = function(evt) {
642     if (evt.promise === expectedPromiseGetter()) {
643       t.unreached_func('unhandledrejection event is not supposed to be triggered');
644     }
645   };
646   var handled = function(evt) {
647     if (evt.promise === expectedPromiseGetter()) {
648       t.unreached_func('rejectionhandled event is not supposed to be triggered');
649     }
650   };
651   addEventListener('unhandledrejection', unhandled);
652   addEventListener('rejectionhandled', handled);
653   ensureCleanup(t, unhandled, handled);
654   setTimeout(function() {
655     t.done();
656   }, 10);
659 function ensureCleanup(t, unhandled, handled) {
660   t.add_cleanup(function() {
661     if (unhandled)
662       removeEventListener('unhandledrejection', unhandled);
663     if (handled)
664       removeEventListener('rejectionhandled', handled);
665   });
668 done();