3 if (self.importScripts) {
4 if ('ServiceWorkerGlobalScope' in self && self instanceof ServiceWorkerGlobalScope) {
5 importScripts('../../serviceworker/resources/worker-testharness.js');
7 importScripts('../../resources/testharness.js');
12 // Straightforward unhandledrejection tests
14 async_test(function(t) {
18 onUnhandledSucceed(t, e, function() { return p; });
20 p = Promise.reject(e);
21 }, 'unhandledrejection: from Promise.reject');
23 async_test(function(t) {
27 onUnhandledSucceed(t, e, function() { return p; });
29 p = new Promise(function(_, reject) {
32 }, 'unhandledrejection: from a synchronous rejection in new Promise');
34 async_test(function(t) {
38 onUnhandledSucceed(t, e, function() { return p; });
40 p = new Promise(function(_, reject) {
41 postMessageTask(function() {
45 }, 'unhandledrejection: from a task-delayed rejection');
47 async_test(function(t) {
51 onUnhandledSucceed(t, e, function() { return p; });
53 p = new Promise(function(_, reject) {
54 setTimeout(function() {
58 }, 'unhandledrejection: from a setTimeout-delayed rejection');
60 async_test(function(t) {
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) {
70 assert_equals(reason, e);
74 }, 'unhandledrejection: from a throw in a rejection handler chained off of Promise.reject');
76 async_test(function(t) {
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() {
88 }).then(unreached, function(reason) {
90 assert_equals(reason, e);
94 }, 'unhandledrejection: from a throw in a rejection handler chained off of a setTimeout-delayed rejection');
96 async_test(function(t) {
101 onUnhandledSucceed(t, e2, function() { return promise2; });
103 var promise = new Promise(function(_, reject) {
104 setTimeout(function() {
106 mutationObserverMicrotask(function() {
107 var unreached = t.unreached_func('promise should not be fulfilled');
108 promise2 = promise.then(unreached, function(reason) {
110 assert_equals(reason, e);
117 }, 'unhandledrejection: from a throw in a rejection handler attached one microtask after a setTimeout-delayed rejection');
119 async_test(function(t) {
123 onUnhandledSucceed(t, e, function() { return p; });
125 p = Promise.resolve().then(function() {
126 return Promise.reject(e);
128 }, 'unhandledrejection: from returning a Promise.reject-created rejection in a fulfillment handler');
130 async_test(function(t) {
134 onUnhandledSucceed(t, e, function() { return p; });
136 p = Promise.resolve().then(function() {
139 }, 'unhandledrejection: from a throw in a fulfillment handler');
141 async_test(function(t) {
145 onUnhandledSucceed(t, e, function() { return p; });
147 p = Promise.resolve().then(function() {
148 return new Promise(function(_, reject) {
149 setTimeout(function() {
154 }, 'unhandledrejection: from returning a setTimeout-delayed rejection in a fulfillment handler');
156 async_test(function(t) {
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) {
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) {
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) {
194 onUnhandledFail(t, function() { return p; });
196 var unreached = t.unreached_func('promise should not be fulfilled');
197 p = new Promise(function(_, reject) {
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) {
207 onUnhandledFail(t, function() { return p; });
209 var unreached = t.unreached_func('promise should not be fulfilled');
210 p = Promise.resolve().then(function() {
212 }).then(unreached, function(reason) {
214 assert_equals(reason, e);
217 }, 'no unhandledrejection/rejectionhandled: rejection handler attached synchronously to a promise created from ' +
218 'throwing in a fulfillment handler');
220 async_test(function(t) {
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) {
231 assert_equals(reason, e);
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) {
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() {
250 }).then(unreached, function(reason) {
252 assert_equals(reason, e);
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) {
262 onUnhandledFail(t, function() { return p; });
264 postMessageTask(function() {
265 p = Promise.resolve().then(function() {
266 return Promise.reject(e);
268 .catch(function() {});
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) {
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() {});
288 }, 'delayed handling: a microtask delay before attaching a handler prevents both events (Promise.reject-created ' +
291 async_test(function(t) {
295 onUnhandledFail(t, function() { return p; });
297 p = new Promise(function(_, reject) {
300 mutationObserverMicrotask(function() {
301 var unreached = t.unreached_func('promise should not be fulfilled');
302 p.then(unreached, function() {});
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) {
312 onUnhandledFail(t, function() { return p1; });
313 onUnhandledFail(t, function() { return p2; });
315 p1 = new Promise(function(_, reject) {
316 mutationObserverMicrotask(function() {
320 p2 = Promise.all([p1]);
321 mutationObserverMicrotask(function() {
322 var unreached = t.unreached_func('promise should not be fulfilled');
323 p2.then(unreached, function() {});
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) {
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() {});
348 }, 'microtask nesting: attaching a handler inside a combination of mutationObserverMicrotask + promise microtasks');
350 async_test(function(t) {
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() {});
368 }, 'microtask nesting: attaching a handler inside a combination of mutationObserverMicrotask + promise microtasks, ' +
369 'all inside a postMessageTask');
371 async_test(function(t) {
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() {});
389 }, 'microtask nesting: attaching a handler inside a combination of mutationObserverMicrotask + promise microtasks, ' +
390 'all inside a setTimeout');
392 async_test(function(t) {
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() {});
408 }, 'microtask nesting: attaching a handler inside a combination of promise microtasks + mutationObserverMicrotask');
410 async_test(function(t) {
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() {});
428 }, 'microtask nesting: attaching a handler inside a combination of promise microtasks + mutationObserverMicrotask, ' +
429 'all inside a postMessageTask');
431 async_test(function(t) {
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() {});
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) {
460 onUnhandledSucceed(t, e, function() { return p; });
463 p = new Promise(function(_, reject) {
467 postMessageTask(function() {
468 var unreached = t.unreached_func('promise should not be fulfilled');
469 p.then(unreached, function() {});
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 = [];
479 var unhandled = function(ev) {
480 if (ev.promise === p) {
482 unhandledPromises.push(ev.promise);
483 unhandledReasons.push(ev.reason);
487 var handled = function(ev) {
488 if (ev.promise === p) {
490 assert_array_equals(unhandledPromises, [p]);
491 assert_array_equals(unhandledReasons, [e]);
492 assert_equals(ev.promise, p);
493 assert_equals(ev.reason, e);
497 addEventListener('unhandledrejection', unhandled);
498 addEventListener('rejectionhandled', handled);
499 ensureCleanup(t, unhandled, handled);
501 p = new Promise(function() {
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);
511 }, 'delayed handling: delaying handling by setTimeout(,10) will cause both events to fire');
513 async_test(function(t) {
517 onUnhandledSucceed(t, e, function() { return p; });
519 p = Promise.reject(e);
520 postMessageTask(function() {
521 Promise.resolve().then(function() {
522 p.catch(function() {});
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) {
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() {});
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) {
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() {});
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) {
575 var l = function(ev) {
577 mutationObserverMicrotask(function() {
580 setTimeout(function() {
583 assert_array_equals(order, [1, 2]);
588 addEventListener('unhandledrejection', l);
591 }, 'mutationObserverMicrotask vs. postMessageTask ordering is not disturbed inside unhandledrejection events');
597 function postMessageTask(f) {
598 if ('document' in self) {
600 removeEventListener('message', l);
603 addEventListener('message', l);
604 postMessage('abusingpostmessageforfunandprofit', '*');
606 var channel = new MessageChannel();
607 channel.port1.onmessage = function() { channel.port1.close(); f(); };
608 channel.port2.postMessage('abusingpostmessageforfunandprofit');
609 channel.port2.close();
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 });
620 // We don't have mutation observers on workers, so just post a promise-based
622 Promise.resolve().then(function() { f(); });
626 function onUnhandledSucceed(t, expectedReason, expectedPromiseGetter) {
627 var l = function(ev) {
628 if (ev.promise === expectedPromiseGetter()) {
630 assert_equals(ev.reason, expectedReason);
631 assert_equals(ev.promise, expectedPromiseGetter());
636 addEventListener('unhandledrejection', 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');
646 var handled = function(evt) {
647 if (evt.promise === expectedPromiseGetter()) {
648 t.unreached_func('rejectionhandled event is not supposed to be triggered');
651 addEventListener('unhandledrejection', unhandled);
652 addEventListener('rejectionhandled', handled);
653 ensureCleanup(t, unhandled, handled);
654 setTimeout(function() {
659 function ensureCleanup(t, unhandled, handled) {
660 t.add_cleanup(function() {
662 removeEventListener('unhandledrejection', unhandled);
664 removeEventListener('rejectionhandled', handled);