Update web-platform-tests to revision 7a767a52741f628430ffbbed46e7f3df68ba3534

Fixes #15648.
This commit is contained in:
Ms2ger 2017-02-20 11:44:42 +01:00
parent a1e4c547f0
commit 4fadf9b0b6
1184 changed files with 22551 additions and 9856 deletions

View file

@ -2,7 +2,6 @@
<meta charset="utf-8">
<title></title>
<body></body>
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>

View file

@ -14,7 +14,7 @@ window.auxClick1Happened = false;
window.auxClick2Happened = false;
test(() => {
for (const location of [window, HTMLElement.prototype, SVGElement.prototype, Document.prototype]) {
for (var location of [window, HTMLElement.prototype, SVGElement.prototype, Document.prototype]) {
assert_true(location.hasOwnProperty("onauxclick"),
`${location.constructor.name} has an own property named "onauxclick"`);
}
@ -24,7 +24,7 @@ test(() => {
const htmlElement = document.createElement("span");
const svgElement = document.createElementNS("http://www.w3.org/2000/svg", "g");
for (const location of [window, htmlElement, svgElement, document]) {
for (var location of [window, htmlElement, svgElement, document]) {
assert_equals(location.onauxclick, null,
`The default value of the property is null for a ${location.constructor.name} instance`);
}

View file

@ -21,21 +21,7 @@
t.done();
}, "mouseover listener returning false doesn't cancel event");
async_test(function(t) {
var ev = new Event('beforeunload', {cancelable: true});
window.onbeforeunload = t.step_func(function() {return null});
window.dispatchEvent(ev);
assert_equals(ev.defaultPrevented, true);
t.done();
}, "beforeunload listener returning null cancels event");
async_test(function(t) {
var ev = new Event('beforeunload', {cancelable: true});
window.onbeforeunload = t.step_func(function() {return true});
window.dispatchEvent(ev);
assert_equals(ev.defaultPrevented, false);
t.done();
}, "beforeunload listener returning non-null doesn't cancel event");
// beforeunload is tested in html/browsers/browsing-the-web/unloading-documents/beforeunload-canceling.html
async_test(function(t) {
var ev = new Event("click", {cancelable: true});

View file

@ -0,0 +1,30 @@
<!DOCTYPE html>
<meta charset="utf-8">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/cors/support.js?pipe=sub"></script>
<link rel="help" href="https://html.spec.whatwg.org/#unhandled-promise-rejections">
<link rel="help" href="https://html.spec.whatwg.org/#muted-errors">
<body>
<script>
'use strict';
setup({
allow_uncaught_exception: true
});
async_test(function(t) {
addEventListener('unhandledrejection', t.step_func(function(e) {
assert_equals(e.reason, 42, 'reason should be the one given by the script');
t.done();
}));
}, 'Promise rejection event should be received for the cross-origin CORS script');
(function() {
var scriptEl = document.createElement('script');
scriptEl.src = CROSSDOMAIN + 'support/promise-access-control.py?allow=true';
scriptEl.crossOrigin = 'anonymous';
document.body.appendChild(scriptEl);
}());
</script>
</body>

View file

@ -0,0 +1,34 @@
<!DOCTYPE html>
<meta charset="utf-8">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/cors/support.js?pipe=sub"></script>
<link rel="help" href="https://html.spec.whatwg.org/#unhandled-promise-rejections">
<link rel="help" href="https://html.spec.whatwg.org/#muted-errors">
<body>
<script>
'use strict';
(function() {
var resolveLoaded;
var loadedPromise = new Promise(function(resolve) { resolveLoaded = resolve; });
async_test(function(t) {
addEventListener('unhandledrejection', t.unreached_func('unhandledrejection event should never be triggered'));
addEventListener('rejectionhandled', t.unreached_func('rejectionhandled event should never be triggered'));
loadedPromise.then(t.step_func(function() {
t.step_timeout(function() {
t.done();
}, 1000);
}));
}, 'Promise rejection event should be muted for cross-origin non-CORS script');
var scriptEl = document.createElement('script');
scriptEl.src = CROSSDOMAIN + 'support/promise-access-control.py?allow=false';
scriptEl.onload = resolveLoaded;
document.body.appendChild(scriptEl);
}());
</script>
</body>

View file

@ -0,0 +1,44 @@
<!DOCTYPE html>
<meta charset="utf-8">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<link rel="help" href="https://html.spec.whatwg.org/#the-promiserejectionevent-interface">
<script>
'use strict';
test(function() {
var p = new Promise(function(resolve, reject) {});
// No custom options are passed (besides required promise).
assert_equals(new PromiseRejectionEvent('eventType', { promise: p }).bubbles, false);
assert_equals(new PromiseRejectionEvent('eventType', { promise: p }).cancelable, false);
assert_equals(new PromiseRejectionEvent('eventType', { promise: p }).promise, p);
assert_equals(new PromiseRejectionEvent('eventType', { promise: p }).reason, undefined);
// No promise is passed.
assert_throws(new TypeError(),
function() {
new PromiseRejectionEvent('eventType', { bubbles: false });
},
'Cannot construct PromiseRejectionEventInit without promise');
// bubbles is passed.
assert_equals(new PromiseRejectionEvent('eventType', { bubbles: false, promise: p }).bubbles, false);
assert_equals(new PromiseRejectionEvent('eventType', { bubbles: true, promise: p }).bubbles, true);
// cancelable is passed.
assert_equals(new PromiseRejectionEvent('eventType', { cancelable: false, promise: p }).cancelable, false);
assert_equals(new PromiseRejectionEvent('eventType', { cancelable: true, promise: p }).cancelable, true);
// reason is passed.
var r = new Error();
assert_equals(new PromiseRejectionEvent('eventType', { promise: p, reason: r }).reason, r);
// All initializers are passed.
assert_equals(new PromiseRejectionEvent('eventType', { bubbles: true, cancelable: true, promise: p, reason: r }).bubbles, true);
assert_equals(new PromiseRejectionEvent('eventType', { bubbles: true, cancelable: true, promise: p, reason: r }).cancelable, true);
assert_equals(new PromiseRejectionEvent('eventType', { bubbles: true, cancelable: true, promise: p, reason: r }).promise, p);
assert_equals(new PromiseRejectionEvent('eventType', { bubbles: true, cancelable: true, promise: p, reason: r }).reason, r);
}, "This tests the constructor for the PromiseRejectionEvent DOM class.");
</script>

View file

@ -0,0 +1,31 @@
<!DOCTYPE html>
<meta charset="utf-8">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<link rel="help" href="https://html.spec.whatwg.org/#unhandled-promise-rejections">
<script>
'use strict';
setup({
allow_uncaught_exception: true
});
async_test(function(t) {
var e = new Error('e');
var p = Promise.reject(e);
window.onunhandledrejection = function(evt) {
t.step(function() {
assert_equals(evt.promise, p);
assert_equals(evt.reason, e);
});
var unreached = t.unreached_func('promise should not be fulfilled');
p.then(unreached, function(reason) {
t.step(function() {
assert_equals(reason, e);
});
t.step_timeout(function() { t.done(); }, 10);
});
};
window.onrejectionhandled = t.unreached_func('rejectionhandled event should not be invoked');
}, 'Attaching a handler in unhandledrejection should not trigger rejectionhandled.');
</script>

View file

@ -0,0 +1,35 @@
<!DOCTYPE html>
<meta charset="utf-8">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<link rel="help" href="https://html.spec.whatwg.org/#runtime-script-errors">
<link rel="help" href="https://html.spec.whatwg.org/#unhandled-promise-rejections">
<script>
'use strict';
setup({
allow_uncaught_exception: true
});
async_test(function(t) {
var e = new Error('e');
var e2 = new Error('e2');
window.onerror = function (msg, url, line, col, error) {
t.step(function() {
assert_equals(msg, 'Uncaught Error: e2');
assert_equals(error, e2);
});
t.done();
};
window.onrejectionhandled = function() {
// This should cause onerror
throw e2;
};
var p = Promise.reject(e);
setTimeout(t.step_func(function() {
// This will cause onrejectionhandled
p.catch(function() {});
}), 1);
}, 'Throwing inside an unhandledrejection handler invokes the error handler.');
</script>

View file

@ -0,0 +1,11 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Promise rejection events tests: in a dedicated worker context</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<link rel="help" href="https://html.spec.whatwg.org/#unhandled-promise-rejections">
<script>
'use strict';
fetch_tests_from_worker(new Worker('support/promise-rejection-events.js'));
</script>

View file

@ -0,0 +1,8 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Promise rejection events tests: in a Window context</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<link rel="help" href="https://html.spec.whatwg.org/#unhandled-promise-rejections">
<script src="support/promise-rejection-events.js"></script>

View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Promise rejection events tests: in a service worker context</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
<link rel="help" href="https://html.spec.whatwg.org/#unhandled-promise-rejections">
<script>
'use strict';
service_worker_test('support/promise-rejection-events.js', 'Service worker setup');
</script>

View file

@ -0,0 +1,11 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Promise rejection events tests: in a shared worker context</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<link rel="help" href="https://html.spec.whatwg.org/#unhandled-promise-rejections">
<script>
'use strict';
fetch_tests_from_worker(new SharedWorker('support/promise-rejection-events.js'));
</script>

View file

@ -0,0 +1,10 @@
def main(request, response):
allow = request.GET.first("allow", "false")
headers = [("Content-Type", "application/javascript")]
if allow != "false":
headers.append(("Access-Control-Allow-Origin", "*"))
body = "new Promise(function(resolve, reject) { reject(42); })"
return headers, body

View file

@ -0,0 +1,900 @@
'use strict';
if (self.importScripts) {
importScripts('/resources/testharness.js');
}
setup({
allow_uncaught_exception: true
});
//
// 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);
mutationObserverMicrotask(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 microtask-delayed attachment
//
async_test(function(t) {
var e = new Error();
var p;
onUnhandledFail(t, function() { return p; });
p = Promise.reject(e);
mutationObserverMicrotask(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);
});
mutationObserverMicrotask(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) {
mutationObserverMicrotask(function() {
reject(e);
});
});
p2 = Promise.all([p1]);
mutationObserverMicrotask(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');
//
// Negative unhandledrejection/rejectionhandled tests with nested-microtask-delayed attachment
//
async_test(function(t) {
var e = new Error();
var p;
onUnhandledFail(t, function() { return p; });
p = Promise.reject(e);
mutationObserverMicrotask(function() {
Promise.resolve().then(function() {
mutationObserverMicrotask(function() {
Promise.resolve().then(function() {
p.catch(function() {});
});
});
});
});
}, 'microtask nesting: attaching a handler inside a combination of mutationObserverMicrotask + promise microtasks');
async_test(function(t) {
var e = new Error();
var p;
onUnhandledFail(t, function() { return p; });
postMessageTask(function() {
p = Promise.reject(e);
mutationObserverMicrotask(function() {
Promise.resolve().then(function() {
mutationObserverMicrotask(function() {
Promise.resolve().then(function() {
p.catch(function() {});
});
});
});
});
});
}, 'microtask nesting: attaching a handler inside a combination of mutationObserverMicrotask + promise microtasks, ' +
'all inside a postMessageTask');
async_test(function(t) {
var e = new Error();
var p;
onUnhandledFail(t, function() { return p; });
setTimeout(function() {
p = Promise.reject(e);
mutationObserverMicrotask(function() {
Promise.resolve().then(function() {
mutationObserverMicrotask(function() {
Promise.resolve().then(function() {
p.catch(function() {});
});
});
});
});
}, 0);
}, 'microtask nesting: attaching a handler inside a combination of mutationObserverMicrotask + promise microtasks, ' +
'all inside a setTimeout');
async_test(function(t) {
var e = new Error();
var p;
onUnhandledFail(t, function() { return p; });
p = Promise.reject(e);
Promise.resolve().then(function() {
mutationObserverMicrotask(function() {
Promise.resolve().then(function() {
mutationObserverMicrotask(function() {
p.catch(function() {});
});
});
});
});
}, 'microtask nesting: attaching a handler inside a combination of promise microtasks + mutationObserverMicrotask');
async_test(function(t) {
var e = new Error();
var p;
onUnhandledFail(t, function() { return p; });
postMessageTask(function() {
p = Promise.reject(e);
Promise.resolve().then(function() {
mutationObserverMicrotask(function() {
Promise.resolve().then(function() {
mutationObserverMicrotask(function() {
p.catch(function() {});
});
});
});
});
});
}, 'microtask nesting: attaching a handler inside a combination of promise microtasks + mutationObserverMicrotask, ' +
'all inside a postMessageTask');
async_test(function(t) {
var e = new Error();
var p;
onUnhandledFail(t, function() { return p; });
setTimeout(function() {
p = Promise.reject(e);
Promise.resolve().then(function() {
mutationObserverMicrotask(function() {
Promise.resolve().then(function() {
mutationObserverMicrotask(function() {
p.catch(function() {});
});
});
});
});
}, 0);
}, 'microtask nesting: attaching a handler inside a combination of promise microtasks + mutationObserverMicrotask, ' +
'all inside a setTimeout');
// For workers, postMessageTask() involves posting tasks to other threads, so
// the following tests don't work there.
if ('document' in self) {
//
// Negative unhandledrejection/rejectionhandled tests with task-delayed attachment
//
async_test(function(t) {
var e = new Error();
var p;
onUnhandledFail(t, 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 prevents unhandledrejection');
async_test(function(t) {
var e = new Error();
var p;
onUnhandledFail(t, 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 not too late to ' +
'attach a rejection handler');
async_test(function(t) {
var e = new Error();
var p;
onUnhandledFail(t, 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 not too ' +
'late to attach a rejection handler');
async_test(function(t) {
var e = new Error();
var p;
onUnhandledFail(t, 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 not too ' +
'late to attach a rejection handler');
}
//
// 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() {
postMessageTask(function() {
var unreached = t.unreached_func('promise should not be fulfilled');
p.then(unreached, function() {});
});
});
}, 'delayed handling: a nested-task delay before attaching a handler causes unhandledrejection');
async_test(function(t) {
var e = new Error();
var p;
onUnhandledSucceed(t, e, function() { return p; });
p = Promise.reject(e);
postMessageTask(function() {
postMessageTask(function() {
Promise.resolve().then(function() {
p.catch(function() {});
});
});
});
}, 'delayed handling: a nested-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() {
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: a nested-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() {
postMessageTask(function() {
Promise.resolve().then(function() {
Promise.resolve().then(function() {
Promise.resolve().then(function() {
Promise.resolve().then(function() {
p.catch(function() {});
});
});
});
});
});
});
}, 'delayed handling: a nested-postMessageTask after promise creation/rejection, plus many promise microtasks, is ' +
'too late to attach a rejection handler');
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');
//
// Miscellaneous tests about integration with the rest of the platform
//
async_test(function(t) {
var e = new Error();
var l = function(ev) {
var order = [];
mutationObserverMicrotask(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);
}, 'mutationObserverMicrotask vs. postMessageTask ordering is not disturbed inside unhandledrejection events');
// For workers, postMessageTask() involves posting tasks to other threads, so
// the following tests don't work there.
if ('document' in self) {
// For the next two see https://github.com/domenic/unhandled-rejections-browser-spec/issues/2#issuecomment-121121695
// and the following comments.
async_test(function(t) {
var sequenceOfEvents = [];
addEventListener('unhandledrejection', l);
ensureCleanup(t, l);
var p1 = Promise.reject();
var p2;
postMessageTask(function() {
p2 = Promise.reject();
postMessageTask(function() {
sequenceOfEvents.push('postMessageTask');
checkSequence();
});
});
function l(ev) {
if (ev.promise === p1 || ev.promise === p2) {
sequenceOfEvents.push(ev.promise);
checkSequence();
}
}
function checkSequence() {
if (sequenceOfEvents.length === 3) {
t.step(function() {
assert_array_equals(sequenceOfEvents, [p1, 'postMessageTask', p2]);
});
t.done();
}
}
}, 'postMessageTask ordering vs. the task queued for unhandled rejection notification (1)');
async_test(function(t) {
var sequenceOfEvents = [];
addEventListener('unhandledrejection', l);
ensureCleanup(t, l);
var p2;
postMessageTask(function() {
p2 = Promise.reject();
postMessageTask(function() {
sequenceOfEvents.push('postMessageTask');
checkSequence();
});
});
function l(ev) {
if (ev.promise == p2) {
sequenceOfEvents.push(ev.promise);
checkSequence();
}
}
function checkSequence() {
if (sequenceOfEvents.length === 2) {
t.step(function() {
assert_array_equals(sequenceOfEvents, ['postMessageTask', p2]);
});
t.done();
}
}
}, 'postMessageTask ordering vs. the task queued for unhandled rejection notification (2)');
async_test(function(t) {
var sequenceOfEvents = [];
addEventListener('unhandledrejection', unhandled);
addEventListener('rejectionhandled', handled);
ensureCleanup(t, unhandled, handled);
var p = Promise.reject();
setTimeout(function() {
postMessageTask(function() {
sequenceOfEvents.push('task before catch');
checkSequence();
});
p.catch(function() {
sequenceOfEvents.push('catch');
checkSequence();
});
postMessageTask(function() {
sequenceOfEvents.push('task after catch');
checkSequence();
});
sequenceOfEvents.push('after catch');
checkSequence();
}, 10);
function unhandled(ev) {
if (ev.promise === p) {
sequenceOfEvents.push('unhandled');
checkSequence();
}
}
function handled(ev) {
if (ev.promise === p) {
sequenceOfEvents.push('handled');
checkSequence();
}
}
function checkSequence() {
if (sequenceOfEvents.length === 6) {
t.step(function() {
assert_array_equals(sequenceOfEvents,
['unhandled', 'after catch', 'catch', 'task before catch', 'handled', 'task after catch']);
});
t.done();
}
}
}, 'rejectionhandled is dispatched from a queued task, and not immediately');
}
//
// HELPERS
//
var globalPostMessageCounter = 0;
function postMessageTask(f) {
if ('document' in self) {
var message = 'abusingpostmessageforfunandprofit' + globalPostMessageCounter;
globalPostMessageCounter++;
var l = function(ev) {
if (ev.data === message) {
removeEventListener('message', l);
f();
}
};
addEventListener('message', l);
postMessage(message, '*');
} else {
var channel = new MessageChannel();
channel.port1.onmessage = function() { channel.port1.close(); f(); };
channel.port2.postMessage('abusingpostmessageforfunandprofit');
channel.port2.close();
}
}
function mutationObserverMicrotask(f) {
if ('document' in self) {
var observer = new MutationObserver(function() { f(); });
var node = document.createTextNode('');
observer.observe(node, { characterData: true });
node.data = 'foo';
} else {
// We don't have mutation observers on workers, so just post a promise-based
// microtask.
Promise.resolve().then(function() { f(); });
}
}
function onUnhandledSucceed(t, expectedReason, expectedPromiseGetter) {
var l = function(ev) {
if (ev.promise === expectedPromiseGetter()) {
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.step(function() {
assert_unreached('unhandledrejection event is not supposed to be triggered');
});
}
};
var handled = function(evt) {
if (evt.promise === expectedPromiseGetter()) {
t.step(function() {
assert_unreached('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();