Chromium Code Reviews| Index: LayoutTests/fast/dom/resources/promise-rejection-events.js |
| diff --git a/LayoutTests/fast/dom/resources/promise-rejection-events.js b/LayoutTests/fast/dom/resources/promise-rejection-events.js |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..d5e1f8f0b653af7c7b1d5b15b190dccb465c3f11 |
| --- /dev/null |
| +++ b/LayoutTests/fast/dom/resources/promise-rejection-events.js |
| @@ -0,0 +1,439 @@ |
| +'use strict'; |
| +if (self.importScripts) { |
| + self.importScripts('../../../resources/testharness.js'); |
| +} |
| +// |
|
domenic
2015/06/16 15:42:36
You killed all my nice separating newlines :(
jochen (gone - plz use gerrit)
2015/06/16 18:08:18
I blame this on paste... I'll put them back in
|
| +// Straightforward unhandledrejection tests |
| +// |
| +async_test(function(t) { |
| + var e = new Error(); |
| + var p; |
| + onUnhandledSucceed(t, e, function() { return p; }); |
| + p = Promise.reject(e); |
| +}, 'unhandledrejection: from Promise.reject'); |
| +async_test(function(t) { |
| + var e = new Error(); |
| + var p; |
| + onUnhandledSucceed(t, e, function() { return p; }); |
| + p = new Promise(function(_, reject) { |
| + reject(e); |
| + }); |
| +}, 'unhandledrejection: from a synchronous rejection in new Promise'); |
| +async_test(function(t) { |
| + var e = new Error(); |
| + var p; |
| + onUnhandledSucceed(t, e, function() { return p; }); |
| + p = new Promise(function(_, reject) { |
| + postMessageTask(function() { |
| + reject(e); |
| + }); |
| + }); |
| +}, 'unhandledrejection: from a task-delayed rejection'); |
| +async_test(function(t) { |
| + var e = new Error(); |
| + var p; |
| + onUnhandledSucceed(t, e, function() { return p; }); |
| + p = new Promise(function(_, reject) { |
| + setTimeout(function() { |
| + reject(e); |
| + }, 1); |
| + }); |
| +}, 'unhandledrejection: from a setTimeout-delayed rejection'); |
| +async_test(function(t) { |
| + var e = new Error(); |
| + var e2 = new Error(); |
| + var promise2; |
| + onUnhandledSucceed(t, e2, function() { return promise2; }); |
| + var unreached = t.unreached_func('promise should not be fulfilled'); |
| + promise2 = Promise.reject(e).then(unreached, function(reason) { |
| + t.step(function() { |
| + assert_equals(reason, e); |
| + }); |
| + throw e2; |
| + }); |
| +}, 'unhandledrejection: from a throw in a rejection handler chained off of Promise.reject'); |
| +async_test(function(t) { |
| + var e = new Error(); |
| + var e2 = new Error(); |
| + var promise2; |
| + onUnhandledSucceed(t, e2, function() { return promise2; }); |
| + var unreached = t.unreached_func('promise should not be fulfilled'); |
| + promise2 = new Promise(function(_, reject) { |
| + setTimeout(function() { |
| + reject(e); |
| + }, 1); |
| + }).then(unreached, function(reason) { |
| + t.step(function() { |
| + assert_equals(reason, e); |
| + }); |
| + throw e2; |
| + }); |
| +}, 'unhandledrejection: from a throw in a rejection handler chained off of a setTimeout-delayed rejection'); |
| +async_test(function(t) { |
| + var e = new Error(); |
| + var e2 = new Error(); |
| + var promise2; |
| + onUnhandledSucceed(t, e2, function() { return promise2; }); |
| + var promise = new Promise(function(_, reject) { |
| + setTimeout(function() { |
| + reject(e); |
| + postMicroTask(function() { |
| + var unreached = t.unreached_func('promise should not be fulfilled'); |
| + promise2 = promise.then(unreached, function(reason) { |
| + t.step(function() { |
| + assert_equals(reason, e); |
| + }); |
| + throw e2; |
| + }); |
| + }); |
| + }, 1); |
| + }); |
| +}, 'unhandledrejection: from a throw in a rejection handler attached one microtask after a setTimeout-delayed rejection'); |
| +async_test(function(t) { |
| + var e = new Error(); |
| + var p; |
| + onUnhandledSucceed(t, e, function() { return p; }); |
| + p = Promise.resolve().then(function() { |
| + return Promise.reject(e); |
| + }); |
| +}, 'unhandledrejection: from returning a Promise.reject-created rejection in a fulfillment handler'); |
| +async_test(function(t) { |
| + var e = new Error(); |
| + var p; |
| + onUnhandledSucceed(t, e, function() { return p; }); |
| + p = Promise.resolve().then(function() { |
| + throw e; |
| + }); |
| +}, 'unhandledrejection: from a throw in a fulfillment handler'); |
| +async_test(function(t) { |
| + var e = new Error(); |
| + var p; |
| + onUnhandledSucceed(t, e, function() { return p; }); |
| + p = Promise.resolve().then(function() { |
| + return new Promise(function(_, reject) { |
| + setTimeout(function() { |
| + reject(e); |
| + }, 1); |
| + }); |
| + }); |
| +}, 'unhandledrejection: from returning a setTimeout-delayed rejection in a fulfillment handler'); |
| +async_test(function(t) { |
| + var e = new Error(); |
| + var p; |
| + onUnhandledSucceed(t, e, function() { return p; }); |
| + p = Promise.all([Promise.reject(e)]); |
| +}, 'unhandledrejection: from Promise.reject, indirected through Promise.all'); |
| +// |
| +// Negative unhandledrejection/rejectionhandled tests with immediate attachment |
| +// |
| +async_test(function(t) { |
| + var e = new Error(); |
| + var p; |
| + onUnhandledFail(t, function() { return p; }); |
| + var unreached = t.unreached_func('promise should not be fulfilled'); |
| + p = Promise.reject(e).then(unreached, function() {}); |
| +}, 'no unhandledrejection/rejectionhandled: rejection handler attached synchronously to a promise from Promise.reject'); |
| +async_test(function(t) { |
| + var e = new Error(); |
| + var p; |
| + onUnhandledFail(t, function() { return p; }); |
| + var unreached = t.unreached_func('promise should not be fulfilled'); |
| + p = Promise.all([Promise.reject(e)]).then(unreached, function() {}); |
| +}, 'no unhandledrejection/rejectionhandled: rejection handler attached synchronously to a promise from ' + |
| + 'Promise.reject, indirecting through Promise.all'); |
| +async_test(function(t) { |
| + var e = new Error(); |
| + var p; |
| + onUnhandledFail(t, function() { return p; }); |
| + var unreached = t.unreached_func('promise should not be fulfilled'); |
| + p = new Promise(function(_, reject) { |
| + reject(e); |
| + }).then(unreached, function() {}); |
| +}, 'no unhandledrejection/rejectionhandled: rejection handler attached synchronously to a synchronously-rejected ' + |
| + 'promise created with new Promise'); |
| +async_test(function(t) { |
| + var e = new Error(); |
| + var p; |
| + onUnhandledFail(t, function() { return p; }); |
| + var unreached = t.unreached_func('promise should not be fulfilled'); |
| + p = Promise.resolve().then(function() { |
| + throw e; |
| + }).then(unreached, function(reason) { |
| + t.step(function() { |
| + assert_equals(reason, e); |
| + }); |
| + }); |
| +}, 'no unhandledrejection/rejectionhandled: rejection handler attached synchronously to a promise created from ' + |
| + 'throwing in a fulfillment handler'); |
| +async_test(function(t) { |
| + var e = new Error(); |
| + var p; |
| + onUnhandledFail(t, function() { return p; }); |
| + var unreached = t.unreached_func('promise should not be fulfilled'); |
| + p = Promise.resolve().then(function() { |
| + return Promise.reject(e); |
| + }).then(unreached, function(reason) { |
| + t.step(function() { |
| + assert_equals(reason, e); |
| + }); |
| + }); |
| +}, 'no unhandledrejection/rejectionhandled: rejection handler attached synchronously to a promise created from ' + |
| + 'returning a Promise.reject-created promise in a fulfillment handler'); |
| +async_test(function(t) { |
| + var e = new Error(); |
| + var p; |
| + onUnhandledFail(t, function() { return p; }); |
| + var unreached = t.unreached_func('promise should not be fulfilled'); |
| + p = Promise.resolve().then(function() { |
| + return new Promise(function(_, reject) { |
| + setTimeout(function() { |
| + reject(e); |
| + }, 1); |
| + }); |
| + }).then(unreached, function(reason) { |
| + t.step(function() { |
| + assert_equals(reason, e); |
| + }); |
| + }); |
| +}, 'no unhandledrejection/rejectionhandled: rejection handler attached synchronously to a promise created from ' + |
| + 'returning a setTimeout-delayed rejection in a fulfillment handler'); |
| +async_test(function(t) { |
| + var e = new Error(); |
| + var p; |
| + onUnhandledFail(t, function() { return p; }); |
| + postMessageTask(function() { |
| + p = Promise.resolve().then(function() { |
| + return Promise.reject(e); |
| + }) |
| + .catch(function() {}); |
| + }); |
| +}, 'no unhandledrejection/rejectionhandled: all inside a queued task, a rejection handler attached synchronously to ' + |
| + 'a promise created from returning a Promise.reject-created promise in a fulfillment handler'); |
| +// |
| +// Negative unhandledrejection/rejectionhandled tests with delayed attachment |
| +// |
| +async_test(function(t) { |
| + var e = new Error(); |
| + var p; |
| + onUnhandledFail(t, function() { return p; }); |
| + p = Promise.reject(e); |
| + postMicroTask(function() { |
| + var unreached = t.unreached_func('promise should not be fulfilled'); |
| + p.then(unreached, function() {}); |
| + }); |
| +}, 'delayed handling: a microtask delay before attaching a handler prevents both events (Promise.reject-created ' + |
| + 'promise)'); |
| +async_test(function(t) { |
| + var e = new Error(); |
| + var p; |
| + onUnhandledFail(t, function() { return p; }); |
| + p = new Promise(function(_, reject) { |
| + reject(e); |
| + }); |
| + postMicroTask(function() { |
| + var unreached = t.unreached_func('promise should not be fulfilled'); |
| + p.then(unreached, function() {}); |
| + }); |
| +}, 'delayed handling: a microtask delay before attaching a handler prevents both events (immediately-rejected new ' + |
| + 'Promise-created promise)'); |
| +async_test(function(t) { |
| + var e = new Error(); |
| + var p1; |
| + var p2; |
| + onUnhandledFail(t, function() { return p1; }); |
| + onUnhandledFail(t, function() { return p2; }); |
| + p1 = new Promise(function(_, reject) { |
| + postMicroTask(function() { |
| + reject(e); |
| + }); |
| + }); |
| + p2 = Promise.all([p1]); |
| + postMicroTask(function() { |
| + var unreached = t.unreached_func('promise should not be fulfilled'); |
| + p2.then(unreached, function() {}); |
| + }); |
| +}, 'delayed handling: a microtask delay before attaching the handler, and before rejecting the promise, indirected ' + |
| + 'through Promise.all'); |
| +// |
| +// Positive unhandledrejection/rejectionhandled tests with delayed attachment |
| +// |
| +async_test(function(t) { |
| + var e = new Error(); |
| + var p; |
| + onUnhandledSucceed(t, e, function() { return p; }); |
| + var _reject; |
| + p = new Promise(function(_, reject) { |
| + _reject = reject; |
| + }); |
| + _reject(e); |
| + postMessageTask(function() { |
| + var unreached = t.unreached_func('promise should not be fulfilled'); |
| + p.then(unreached, function() {}); |
| + }); |
| +}, 'delayed handling: a task delay before attaching a handler does not prevent unhandledrejection'); |
| +async_test(function(t) { |
| + var unhandledPromises = []; |
| + var unhandledReasons = []; |
| + var e = new Error(); |
| + var p; |
| + var unhandled = function(ev) { |
| + if (ev.promise === p) { |
| + t.step(function() { |
| + unhandledPromises.push(ev.promise); |
| + unhandledReasons.push(ev.reason); |
| + }); |
| + } |
| + }; |
| + var handled = function(ev) { |
| + if (ev.promise === p) { |
| + t.step(function() { |
| + assert_array_equals(unhandledPromises, [p]); |
| + assert_array_equals(unhandledReasons, [e]); |
| + assert_equals(ev.promise, p); |
| + assert_equals(ev.reason, e); |
| + }); |
| + } |
| + }; |
| + addEventListener('unhandledrejection', unhandled); |
| + addEventListener('rejectionhandled', handled); |
| + ensureCleanup(t, unhandled, handled); |
| + p = new Promise(function() { |
| + throw e; |
| + }); |
| + setTimeout(function() { |
| + var unreached = t.unreached_func('promise should not be fulfilled'); |
| + p.then(unreached, function(reason) { |
| + assert_equals(reason, e); |
| + setTimeout(function() { t.done(); }, 10); |
| + }); |
| + }, 10); |
| +}, 'delayed handling: delaying handling by setTimeout(,10) will cause both events to fire'); |
| +async_test(function(t) { |
| + var e = new Error(); |
| + var p; |
| + onUnhandledSucceed(t, e, function() { return p; }); |
| + p = Promise.reject(e); |
| + postMessageTask(function() { |
| + Promise.resolve().then(function() { |
| + p.catch(function() {}); |
| + }); |
| + }); |
| +}, 'delayed handling: postMessageTask after promise creation/rejection, plus promise microtasks, is too late to ' + |
| + 'attach a rejection handler'); |
| +async_test(function(t) { |
| + var e = new Error(); |
| + var p; |
| + onUnhandledSucceed(t, e, function() { return p; }); |
| + postMessageTask(function() { |
| + Promise.resolve().then(function() { |
| + Promise.resolve().then(function() { |
| + Promise.resolve().then(function() { |
| + Promise.resolve().then(function() { |
| + p.catch(function() {}); |
| + }); |
| + }); |
| + }); |
| + }); |
| + }); |
| + p = Promise.reject(e); |
| +}, 'delayed handling: postMessageTask before promise creation/rejection, plus many promise microtasks, is too late ' + |
| + 'to attach a rejection handler'); |
| +async_test(function(t) { |
| + var e = new Error(); |
| + var p; |
| + onUnhandledSucceed(t, e, function() { return p; }); |
| + p = Promise.reject(e); |
| + postMessageTask(function() { |
| + Promise.resolve().then(function() { |
| + Promise.resolve().then(function() { |
| + Promise.resolve().then(function() { |
| + Promise.resolve().then(function() { |
| + p.catch(function() {}); |
| + }); |
| + }); |
| + }); |
| + }); |
| + }); |
| +}, 'delayed handling: postMessageTask after promise creation/rejection, plus many promise microtasks, is too late ' + |
| + 'to attach a rejection handler'); |
| +// |
| +// Miscellaneous tests about integration with the rest of the platform |
| +// |
| +async_test(function(t) { |
| + var e = new Error(); |
| + var l = function(ev) { |
| + var order = []; |
| + postMicroTask(function() { |
| + order.push(1); |
| + }); |
| + setTimeout(function() { |
| + order.push(2); |
| + t.step(function() { |
| + assert_array_equals(order, [1, 2]); |
| + }); |
| + t.done(); |
| + }, 1); |
| + }; |
| + addEventListener('unhandledrejection', l); |
| + ensureCleanup(t, l); |
| + Promise.reject(e); |
| +}, 'postMicroTask vs. postMessageTask ordering is not disturbed inside unhandledrejection events'); |
| +// |
| +// HELPERS |
| +// |
| +function postMessageTask(f) { |
| + if ('document' in self) { |
| + var l = function() { |
| + removeEventListener('message', l); |
| + f(); |
| + }; |
| + addEventListener('message', l); |
| + postMessage('abusingpostmessageforfunandprofit', '*'); |
| + } else { |
| + setTimeout(function() { f(); }, 0); |
|
domenic
2015/06/16 15:42:36
Should use MessageChannel in workers. https://gith
jochen (gone - plz use gerrit)
2015/06/17 07:57:53
done
|
| + } |
| +} |
| +function postMicroTask(f) { |
| + Promise.resolve().then(function() { f(); }); |
|
domenic
2015/06/16 15:42:36
Kind of the point of the microtask tests is to tes
jochen (gone - plz use gerrit)
2015/06/16 18:08:18
i'll put them back.
from an implementation point
|
| +} |
| +function onUnhandledSucceed(t, expectedReason, expectedPromiseGetter) { |
| + var l = function(ev) { |
| + if (ev.promise === expectedPromiseGetter()) { |
|
domenic
2015/06/16 15:42:36
This if seems bad. If they mismatch, then the test
jochen (gone - plz use gerrit)
2015/06/16 18:08:18
without this, none of the tests will work, as they
|
| + t.step(function() { |
| + assert_equals(ev.reason, expectedReason); |
| + assert_equals(ev.promise, expectedPromiseGetter()); |
| + }); |
| + t.done(); |
| + } |
| + }; |
| + addEventListener('unhandledrejection', l); |
| + ensureCleanup(t, l); |
| +} |
| +function onUnhandledFail(t, expectedPromiseGetter) { |
| + var unhandled = function(evt) { |
| + if (evt.promise === expectedPromiseGetter()) { |
| + t.unreached_func('unhandledrejection event is not supposed to be triggered'); |
| + } |
| + }; |
| + var handled = function(evt) { |
| + if (evt.promise === expectedPromiseGetter()) { |
| + t.unreached_func('rejectionhandled event is not supposed to be triggered'); |
| + } |
| + }; |
| + addEventListener('unhandledrejection', unhandled); |
| + addEventListener('rejectionhandled', handled); |
| + ensureCleanup(t, unhandled, handled); |
| + setTimeout(function() { |
| + t.done(); |
| + }, 10); |
| +} |
| +function ensureCleanup(t, unhandled, handled) { |
| + t.add_cleanup(function() { |
| + if (unhandled) |
| + removeEventListener('unhandledrejection', unhandled); |
| + if (handled) |
| + removeEventListener('rejectionhandled', handled); |
| + }); |
| +} |
| + |
| +done(); |