Update web-platform-tests to revision b7a8b84debb42268ea95a45bdad8f727d1facdf7

This commit is contained in:
WPT Sync Bot 2019-03-21 21:40:20 -04:00
parent ba929208e4
commit 953dbda9a6
215 changed files with 6409 additions and 1644 deletions

View file

@ -1,4 +1,5 @@
<!DOCTYPE html>
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<script src="resources/testharness-helpers.js"></script>
<script src="/resources/testharnessreport.js"></script>
@ -56,21 +57,25 @@ function msg_event_test(scope, test) {
}
promise_test(msg_event_test.bind(this, 'no-current-extension-different-task'),
'Test calling waitUntil in a different task without an existing extension throws');
'Test calling waitUntil in a task at the end of the event handler without an existing extension throws');
promise_test(msg_event_test.bind(this, 'no-current-extension-different-microtask'),
'Test calling waitUntil in a different microtask without an existing extension throws');
'Test calling waitUntil in a microtask at the end of the event handler without an existing extension suceeds');
promise_test(msg_event_test.bind(this, 'current-extension-different-task'),
'Test calling waitUntil in a different task with an existing extension succeeds');
'Test calling waitUntil in a different task an existing extension succeeds');
promise_test(msg_event_test.bind(this, 'current-extension-expired-same-microtask-turn'),
'Test calling waitUntil with an existing extension promise handler succeeds');
promise_test(msg_event_test.bind(this, 'during-event-dispatch-current-extension-expired-same-microtask-turn'),
'Test calling waitUntil at the end of an existing extension promise handler succeeds (event is still being dispatched)');
// The promise handler will queue a new microtask after the check for new
// extensions was performed.
promise_test(msg_event_test.bind(this, 'current-extension-expired-same-microtask-turn-extra'),
'Test calling waitUntil at the end of the microtask turn throws');
promise_test(msg_event_test.bind(this, 'during-event-dispatch-current-extension-expired-same-microtask-turn-extra'),
'Test calling waitUntil in a microtask at the end of an existing extension promise handler succeeds (event is still being dispatched)');
promise_test(msg_event_test.bind(this, 'after-event-dispatch-current-extension-expired-same-microtask-turn'),
'Test calling waitUntil in an existing extension promise handler succeeds (event is not being dispatched)');
promise_test(msg_event_test.bind(this, 'after-event-dispatch-current-extension-expired-same-microtask-turn-extra'),
'Test calling waitUntil in a microtask at the end of an existing extension promise handler throws (event is not being dispatched)');
promise_test(msg_event_test.bind(this, 'current-extension-expired-different-task'),
'Test calling waitUntil after the current extension expired in a different task fails');
@ -80,24 +85,36 @@ promise_test(msg_event_test.bind(this, 'script-extendable-event'),
promise_test(function(t) {
var testBody = function(worker) {
return with_iframe('./resources/pending-respondwith-async-waituntil/dummy.html');
return with_iframe('./resources/pending-respondwith-async-waituntil');
}
return runTest(t, 'pending-respondwith-async-waituntil', testBody);
}, 'Test calling waitUntil asynchronously with pending respondWith promise.');
promise_test(function(t) {
var testBody = function(worker) {
return with_iframe('./resources/respondwith-microtask-sync-waituntil/dummy.html');
return with_iframe('./resources/during-event-dispatch-respondwith-microtask-sync-waituntil');
}
return runTest(t, 'respondwith-microtask-sync-waituntil', testBody);
}, 'Test calling waitUntil synchronously inside microtask of respondWith promise.');
return runTest(t, 'during-event-dispatch-respondwith-microtask-sync-waituntil', testBody);
}, 'Test calling waitUntil synchronously inside microtask of respondWith promise (event is being dispatched).');
promise_test(function(t) {
var testBody = function(worker) {
return with_iframe('./resources/respondwith-microtask-async-waituntil/dummy.html');
return with_iframe('./resources/during-event-dispatch-respondwith-microtask-async-waituntil');
}
return runTest(t, 'respondwith-microtask-async-waituntil', testBody);
}, 'Test calling waitUntil asynchronously inside microtask of respondWith promise.');
return runTest(t, 'during-event-dispatch-respondwith-microtask-async-waituntil', testBody);
}, 'Test calling waitUntil asynchronously inside microtask of respondWith promise (event is being dispatched).');
promise_test(function(t) {
var testBody = function(worker) {
return with_iframe('./resources/after-event-dispatch-respondwith-microtask-sync-waituntil');
}
return runTest(t, 'after-event-dispatch-respondwith-microtask-sync-waituntil', testBody);
}, 'Test calling waitUntil synchronously inside microtask of respondWith promise (event is not being dispatched).');
promise_test(function(t) {
var testBody = function(worker) {
return with_iframe('./resources/after-event-dispatch-respondwith-microtask-async-waituntil');
}
return runTest(t, 'after-event-dispatch-respondwith-microtask-async-waituntil', testBody);
}, 'Test calling waitUntil asynchronously inside microtask of respondWith promise (event is not being dispatched).');
</script>

View file

@ -1,36 +1,61 @@
<!DOCTYPE html>
<html>
<title>respondWith cannot be called asynchronously</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<script>
promise_test(function(t) {
var script = 'resources/fetch-event-async-respond-with-worker.js';
var scope = 'resources/simple.html';
// This file has tests that call respondWith() asynchronously.
return service_worker_unregister_and_register(t, script, scope)
.then(function(registration) {
t.add_cleanup(function() {
return service_worker_unregister(t, scope);
});
let frame;
let worker;
const script = 'resources/fetch-event-async-respond-with-worker.js';
const scope = 'resources/simple.html';
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() {
return with_iframe(scope);
})
.then(function(frame) {
add_completion_callback(function() { frame.remove(); });
var channel = new MessageChannel();
var saw_message = new Promise(function(resolve) {
channel.port1.onmessage = function(e) { resolve(e.data); }
});
var worker = frame.contentWindow.navigator.serviceWorker.controller;
// Global setup: this must be the first promise_test.
promise_test(async (t) => {
const registration =
await service_worker_unregister_and_register(t, script, scope);
worker = registration.installing;
await wait_for_state(t, worker, 'activated');
frame = await with_iframe(scope);
}, 'global setup');
worker.postMessage({port: channel.port2}, [channel.port2]);
return saw_message;
})
.then(function(message) {
assert_equals(message, 'PASS');
})
}, 'Calling respondWith asynchronously throws an exception');
// Does one test case. It fetches |url|. The service worker gets a fetch event
// for |url| and attempts to call respondWith() asynchronously. It reports back
// to the test whether an exception was thrown.
async function do_test(url) {
// Send a message to tell the worker a new test case is starting.
const sawMessage = new Promise(resolve => {
navigator.serviceWorker.onmessage = (event) => {
resolve(event.data);
};
worker.postMessage('');
});
// Start a fetch.
frame.contentWindow.fetch(url);
// Receive the test result from the service worker.
return await sawMessage;
};
promise_test(async (t) => {
const result = await do_test('respondWith-in-task');
assert_true(result.didThrow, 'should throw');
assert_equals(result.error, 'InvalidStateError');
}, 'respondWith in a task throws InvalidStateError');
promise_test(async (t) => {
const result = await do_test('respondWith-in-microtask');
assert_equals(result.didThrow, false, 'should not throw');
}, 'respondWith in a microtask does not throw');
// Global cleanup: the final promise_test.
promise_test(async (t) => {
if (frame)
frame.remove();
await service_worker_unregister(t, scope);
}, 'global cleanup');
</script>
</html>

View file

@ -1,4 +1,12 @@
// controlled by 'init'/'done' messages.
// This worker calls waitUntil() and respondWith() asynchronously and
// reports back to the test whether they threw.
//
// These test cases are confusing. Bear in mind that the event is active
// (calling waitUntil() is allowed) if:
// * The pending promise count is not 0, or
// * The event dispatch flag is set.
// Controlled by 'init'/'done' messages.
var resolveLockPromise;
var port;
@ -14,34 +22,72 @@ self.addEventListener('message', function(event) {
case 'done':
resolveLockPromise();
break;
// Throws because waitUntil() is called in a task after event dispatch
// finishes.
case 'no-current-extension-different-task':
async_task_waituntil(event).then(reportResultExpecting('InvalidStateError'));
break;
// OK because waitUntil() is called in a microtask that runs after the
// event handler runs, while the event dispatch flag is still set.
case 'no-current-extension-different-microtask':
async_microtask_waituntil(event).then(reportResultExpecting('InvalidStateError'));
async_microtask_waituntil(event).then(reportResultExpecting('OK'));
break;
// OK because the second waitUntil() is called while the first waitUntil()
// promise is still pending.
case 'current-extension-different-task':
event.waitUntil(new Promise((res) => { resolveTestPromise = res; }));
async_task_waituntil(event).then(reportResultExpecting('OK')).then(resolveTestPromise);
break;
case 'current-extension-expired-same-microtask-turn':
// OK because all promises involved resolve "immediately", so the second
// waitUntil() is called during the microtask checkpoint at the end of
// event dispatching, when the event dispatch flag is still set.
case 'during-event-dispatch-current-extension-expired-same-microtask-turn':
waitPromise = Promise.resolve();
event.waitUntil(waitPromise);
waitPromise.then(() => { return sync_waituntil(event); })
.then(reportResultExpecting('OK'))
break;
case 'current-extension-expired-same-microtask-turn-extra':
// The promise handler queues a new microtask *after* the check for new
// extensions was performed.
// OK for the same reason as above.
case 'during-event-dispatch-current-extension-expired-same-microtask-turn-extra':
waitPromise = Promise.resolve();
event.waitUntil(waitPromise);
waitPromise.then(() => { return async_microtask_waituntil(event); })
.then(reportResultExpecting('OK'))
break;
// OK because the pending promise count is decremented in a microtask
// queued upon fulfillment of the first waitUntil() promise, so the second
// waitUntil() is called while the pending promise count is still
// positive.
case 'after-event-dispatch-current-extension-expired-same-microtask-turn':
waitPromise = makeNewTaskPromise();
event.waitUntil(waitPromise);
waitPromise.then(() => { return sync_waituntil(event); })
.then(reportResultExpecting('OK'))
break;
// Throws because the second waitUntil() is called after the pending
// promise count was decremented to 0.
case 'after-event-dispatch-current-extension-expired-same-microtask-turn-extra':
waitPromise = makeNewTaskPromise();
event.waitUntil(waitPromise);
waitPromise.then(() => { return async_microtask_waituntil(event); })
.then(reportResultExpecting('InvalidStateError'))
break;
// Throws because the second waitUntil() is called in a new task, after
// first waitUntil() promise settled and the event dispatch flag is unset.
case 'current-extension-expired-different-task':
event.waitUntil(Promise.resolve());
async_task_waituntil(event).then(reportResultExpecting('InvalidStateError'));
break;
case 'script-extendable-event':
self.dispatchEvent(new ExtendableEvent('nontrustedevent'));
break;
@ -51,25 +97,62 @@ self.addEventListener('message', function(event) {
});
self.addEventListener('fetch', function(event) {
if (event.request.url.indexOf('pending-respondwith-async-waituntil') != -1) {
const path = new URL(event.request.url).pathname;
const step = path.substring(path.lastIndexOf('/') + 1);
let response;
switch (step) {
// OK because waitUntil() is called while the respondWith() promise is still
// unsettled, so the pending promise count is positive.
case 'pending-respondwith-async-waituntil':
var resolveFetch;
let response = new Promise((res) => { resolveFetch = res; });
response = new Promise((res) => { resolveFetch = res; });
event.respondWith(response);
async_task_waituntil(event)
.then(reportResultExpecting('OK'))
.then(() => { resolveFetch(new Response('OK')); });
} else if (event.request.url.indexOf('respondwith-microtask-sync-waituntil') != -1) {
break;
// OK because all promises involved resolve "immediately", so waitUntil() is
// called during the microtask checkpoint at the end of event dispatching,
// when the event dispatch flag is still set.
case 'during-event-dispatch-respondwith-microtask-sync-waituntil':
response = Promise.resolve(new Response('RESP'));
event.respondWith(response);
response.then(() => { return sync_waituntil(event); })
.then(reportResultExpecting('OK'))
} else if (event.request.url.indexOf('respondwith-microtask-async-waituntil') != -1) {
.then(reportResultExpecting('OK'));
break;
// OK because all promises involved resolve "immediately", so waitUntil() is
// called during the microtask checkpoint at the end of event dispatching,
// when the event dispatch flag is still set.
case 'during-event-dispatch-respondwith-microtask-async-waituntil':
response = Promise.resolve(new Response('RESP'));
event.respondWith(response);
response.then(() => { return async_microtask_waituntil(event); })
.then(reportResultExpecting('OK'));
break;
// OK because the pending promise count is decremented in a microtask queued
// upon fulfillment of the respondWith() promise, so waitUntil() is called
// while the pending promise count is still positive.
case 'after-event-dispatch-respondwith-microtask-sync-waituntil':
response = makeNewTaskPromise().then(() => {return new Response('RESP');});
event.respondWith(response);
response.then(() => { return sync_waituntil(event); })
.then(reportResultExpecting('OK'));
break;
// Throws because waitUntil() is called after the pending promise count was
// decremented to 0.
case 'after-event-dispatch-respondwith-microtask-async-waituntil':
response = makeNewTaskPromise().then(() => {return new Response('RESP');});
event.respondWith(response);
response.then(() => { return async_microtask_waituntil(event); })
.then(reportResultExpecting('InvalidStateError'))
}
});
break;
}
});
self.addEventListener('nontrustedevent', function(event) {
sync_waituntil(event).then(reportResultExpecting('InvalidStateError'));
@ -118,3 +201,10 @@ function async_task_waituntil(event) {
}, 0);
});
}
// Returns a promise that settles in a separate task.
function makeNewTaskPromise() {
return new Promise(resolve => {
setTimeout(resolve, 0);
});
}

View file

@ -1,19 +1,56 @@
var result;
// This worker attempts to call respondWith() asynchronously after the
// fetch event handler finished. It reports back to the test whether
// an exception was thrown.
self.addEventListener('message', function(event) {
event.data.port.postMessage(result);
// These get reset at the start of a test case.
let reportResult;
let resultPromise;
// The test page sends a message to tell us that a new test case is starting.
// We expect a fetch event after this.
self.addEventListener('message', (event) => {
resultPromise = new Promise((resolve) => {
reportResult = resolve;
});
// Keep the worker alive until the test case finishes, and report
// back the result to the test page.
event.waitUntil(resultPromise.then(result => {
event.source.postMessage(result);
}));
});
// Calls respondWith() and reports back whether an exception occurred.
function tryRespondWith(event) {
try {
event.respondWith(new Response());
reportResult({didThrow: false});
} catch (error) {
reportResult({didThrow: true, error: error.name});
}
}
function respondWithInTask(event) {
setTimeout(() => {
tryRespondWith(event);
}, 0);
}
function respondWithInMicrotask(event) {
Promise.resolve().then(() => {
tryRespondWith(event);
});
}
self.addEventListener('fetch', function(event) {
setTimeout(function() {
try {
event.respondWith(new Response());
result = 'FAIL: did not throw';
} catch (error) {
if (error.name == 'InvalidStateError')
result = 'PASS';
else
result = 'FAIL: Unexpected exception: ' + error;
}
}, 0);
});
const path = new URL(event.request.url).pathname;
const test = path.substring(path.lastIndexOf('/') + 1);
// If this is a test case, try respondWith() and report back to the test page
// the result.
if (test == 'respondWith-in-task') {
respondWithInTask(event);
} else if (test == 'respondWith-in-microtask') {
respondWithInMicrotask(event);
}
});