author | Andrew Sutherland <asutherland@asutherland.org> |
Mon, 23 May 2016 22:40:50 -0400 | |
changeset 298833 | 36ed89b1851c88b757a2a2a9a9a911e2598f4f36 |
parent 298832 | 013b6cecd6ead3f2ef504202cbd240ae95d60541 |
child 298834 | 3313a2e169d161104009e905a662e13be8a757f1 |
push id | 30285 |
push user | cbook@mozilla.com |
push date | Wed, 25 May 2016 13:06:07 +0000 |
treeherder | mozilla-central@d6d4e8417d2f [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | bkelly |
bugs | 1273920 |
milestone | 49.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/workers/test/serviceworkers/blocking_install_event_worker.js +++ b/dom/workers/test/serviceworkers/blocking_install_event_worker.js @@ -10,8 +10,14 @@ function postMessageToTest(msg) { }); } addEventListener('install', evt => { // This must be a simple promise to trigger the CC failure. evt.waitUntil(new Promise(function() { })); postMessageToTest({ type: 'INSTALL_EVENT' }); }); + +addEventListener('message', evt => { + if (evt.data.type === 'ping') { + postMessageToTest({ type: 'pong' }); + } +});
--- a/dom/workers/test/serviceworkers/test_install_event_gc.html +++ b/dom/workers/test/serviceworkers/test_install_event_gc.html @@ -33,23 +33,59 @@ function waitForInstallEvent() { if (evt.data.type === 'INSTALL_EVENT') { resolve(); } }); }); } function gcWorker() { - return new Promise(function(resolve) { - // XXX: We need to trigger a CC/GC on the worker thread, but special - // powers does not support that. A setTimeout() longer than our - // CC period is the only solution I have found. - SimpleTest.requestFlakyTimeout('No way to force an immediate CC/GC of a ' + - 'worker JS runtime.'); - setTimeout(resolve, 10000); + 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', null); + SpecialPowers.notifyObservers(null, 'child-cc-request', null); + SpecialPowers.notifyObservers(null, 'child-gc-request', null); + // (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] @@ -78,9 +114,8 @@ SpecialPowers.pushPrefEnv({"set": [ ["dom.serviceWorkers.enabled", true], ["dom.serviceWorkers.testing.enabled", true], ["dom.caches.enabled", true], ]}, runTest); </script> </pre> </body> </html> -