зеркало из https://github.com/mozilla/gecko-dev.git
122 строки
4.4 KiB
HTML
122 строки
4.4 KiB
HTML
<!--
|
|
Any copyright is dedicated to the Public Domain.
|
|
http://creativecommons.org/publicdomain/zero/1.0/
|
|
-->
|
|
<!DOCTYPE HTML>
|
|
<html>
|
|
<head>
|
|
<title>Test install event being GC'd before waitUntil fulfills</title>
|
|
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
|
</head>
|
|
<body>
|
|
<script class="testbody" type="text/javascript">
|
|
var script = 'blocking_install_event_worker.js';
|
|
var scope = 'sw_clients/simple.html?install-event-gc';
|
|
var registration;
|
|
|
|
function register() {
|
|
return navigator.serviceWorker.register(script, { scope })
|
|
.then(swr => registration = swr);
|
|
}
|
|
|
|
function unregister() {
|
|
if (!registration) {
|
|
return;
|
|
}
|
|
return registration.unregister();
|
|
}
|
|
|
|
function waitForInstallEvent() {
|
|
return new Promise((resolve, reject) => {
|
|
navigator.serviceWorker.addEventListener('message', evt => {
|
|
if (evt.data.type === 'INSTALL_EVENT') {
|
|
resolve();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
function gcWorker() {
|
|
return new Promise(function(resolve, reject) {
|
|
// We are able to trigger asynchronous garbage collection and cycle
|
|
// collection by emitting "child-cc-request" and "child-gc-request"
|
|
// observer notifications. The worker RuntimeService will translate
|
|
// these notifications into the appropriate operation on all known
|
|
// worker threads.
|
|
//
|
|
// In the failure case where GC/CC causes us to abort the installation,
|
|
// we will know something happened from the statechange event.
|
|
const statechangeHandler = evt => {
|
|
// Reject rather than resolving to avoid the possibility of us seeing
|
|
// an unrelated racing statechange somehow. Since in the success case we
|
|
// will still see a state change on termination, we do explicitly need to
|
|
// be removed on the success path.
|
|
ok(registration.installing, 'service worker is still installing?');
|
|
reject();
|
|
};
|
|
registration.installing.addEventListener('statechange', statechangeHandler);
|
|
// In the success case since the service worker installation is effectively
|
|
// hung, we instead depend on sending a 'ping' message to the service worker
|
|
// and hearing it 'pong' back. Since we issue our postMessage after we
|
|
// trigger the GC/CC, our 'ping' will only be processed after the GC/CC and
|
|
// therefore the pong will also strictly occur after the cycle collection.
|
|
navigator.serviceWorker.addEventListener('message', evt => {
|
|
if (evt.data.type === 'pong') {
|
|
registration.installing.removeEventListener(
|
|
'statechange', statechangeHandler);
|
|
resolve();
|
|
}
|
|
});
|
|
// At the current time, the service worker will exist in our same process
|
|
// and notifyObservers is synchronous. However, in the future, service
|
|
// workers may end up in a separate process and in that case it will be
|
|
// appropriate to use notifyObserversInParentProcess or something like it.
|
|
// (notifyObserversInParentProcess is a synchronous IPC call to the parent
|
|
// process's main thread. IPDL PContent::CycleCollect is an async message.
|
|
// Ordering will be maintained if the postMessage goes via PContent as well,
|
|
// but that seems unlikely.)
|
|
SpecialPowers.notifyObservers(null, 'child-gc-request');
|
|
SpecialPowers.notifyObservers(null, 'child-cc-request');
|
|
SpecialPowers.notifyObservers(null, 'child-gc-request');
|
|
// (Only send the ping after we set the gc/cc/gc in motion.)
|
|
registration.installing.postMessage({ type: 'ping' });
|
|
});
|
|
}
|
|
|
|
function terminateWorker() {
|
|
return SpecialPowers.pushPrefEnv({
|
|
set: [
|
|
["dom.serviceWorkers.idle_timeout", 0],
|
|
["dom.serviceWorkers.idle_extended_timeout", 0]
|
|
]
|
|
}).then(_ => {
|
|
registration.installing.postMessage({ type: 'RESET_TIMER' });
|
|
});
|
|
}
|
|
|
|
function runTest() {
|
|
Promise.all([
|
|
waitForInstallEvent(),
|
|
register()
|
|
]).then(_ => ok(registration.installing, 'service worker is installing'))
|
|
.then(gcWorker)
|
|
.then(_ => ok(registration.installing, 'service worker is still installing'))
|
|
.then(terminateWorker)
|
|
.catch(e => ok(false, e))
|
|
.then(unregister)
|
|
.then(SimpleTest.finish);
|
|
}
|
|
|
|
SimpleTest.waitForExplicitFinish();
|
|
SpecialPowers.pushPrefEnv({"set": [
|
|
["dom.serviceWorkers.exemptFromPerDomainMax", true],
|
|
["dom.serviceWorkers.enabled", true],
|
|
["dom.serviceWorkers.testing.enabled", true],
|
|
["dom.caches.enabled", true],
|
|
]}, runTest);
|
|
</script>
|
|
</pre>
|
|
</body>
|
|
</html>
|