OLD | NEW |
1 <!DOCTYPE html> | 1 <!DOCTYPE html> |
2 <script src="/js-test-resources/js-test.js"></script> | 2 <script src="/js-test-resources/js-test.js"></script> |
3 <script> | 3 <script> |
4 window.jsTestIsAsync = true; | 4 window.jsTestIsAsync = true; |
5 description('Test that a registered Service Worker with an event handler is not
garbage collected prematurely'); | 5 description('Test that a registered Service Worker with an event handler is not
garbage collected prematurely'); |
6 var swObservation = null; | 6 var service_worker_observation = null; |
| 7 var registration_observation = null; |
7 var scope = 'gc'; | 8 var scope = 'gc'; |
8 | 9 |
9 if (!window.internals) { | 10 if (!window.internals) { |
10 testFailed('This test requires internals.observeGC'); | 11 testFailed('This test requires internals.observeGC'); |
11 finishJSTest(); | 12 finishJSTest(); |
12 } else { | 13 } else { |
13 setup(); | 14 setup(); |
| 15 } |
| 16 |
| 17 function wait_for_state(worker, state) { |
| 18 return new Promise(function(resolve) { |
| 19 worker.onstatechange = function() { |
| 20 if (worker.state == state) |
| 21 resolve(worker); |
| 22 } |
| 23 }); |
| 24 } |
| 25 |
| 26 function wait_for_update(registration) { |
| 27 return new Promise(function(resolve) { |
| 28 registration.addEventListener('updatefound', function() { |
| 29 resolve(registration.installing); |
| 30 }); |
| 31 }); |
14 } | 32 } |
15 | 33 |
16 function setup() { | 34 function setup() { |
17 var worker = '../resources/empty-worker.js'; | 35 var worker_1 = '../resources/empty-worker.js'; |
18 unregisterAndRegister(worker, scope).then(onRegister); | 36 |
| 37 navigator.serviceWorker.unregister(scope) |
| 38 .then(function() { |
| 39 return navigator.serviceWorker.register(worker_1, { scope: scope }); |
| 40 }) |
| 41 .then(function(registration) { |
| 42 registration_observation = internals.observeGC(registration); |
| 43 return wait_for_update(registration); |
| 44 }) |
| 45 .then(function(sw) { |
| 46 service_worker_observation = internals.observeGC(sw); |
| 47 return wait_for_state(sw, 'activated'); |
| 48 }) |
| 49 .then(function(sw) { |
| 50 // Use setTimeout to ensure a fresh stack with no references to |
| 51 // the registration or worker. |
| 52 setTimeout(on_activated, 0); |
| 53 }) |
| 54 .catch(function(error) { |
| 55 testFailed(error.message || error.name || error); |
| 56 finishJSTest(); |
| 57 }); |
19 } | 58 } |
20 | 59 |
21 function unregisterAndRegister(url, scope) { | 60 function on_activated() { |
22 return navigator.serviceWorker.unregister(scope).then(function() { | 61 // The worker has an event handler that can still receive the state change |
23 return navigator.serviceWorker.register(url, { scope: scope }); | 62 // to 'redundant', so it shouldn't be collected yet. |
24 }).catch(function(error) { | 63 gc(); |
25 testFailed('Could not register worker: ' + error); | 64 shouldBeFalse('service_worker_observation.wasCollected'); |
26 finishJSTest(); | 65 shouldBeFalse('registration_observation.wasCollected'); |
27 }); | 66 var worker_2 = '../resources/empty-worker.js?new'; |
28 } | 67 navigator.serviceWorker.register(worker_2, { scope: scope }) |
29 | 68 .then(function(registration) { |
30 function onRegister(sw) { | 69 return wait_for_update(registration); |
31 swObservation = internals.observeGC(sw); | 70 }) |
32 sw.addEventListener('statechange', onStateChange); | 71 .then(function(sw) { |
33 } | 72 return wait_for_state(sw, 'activated'); |
34 | 73 }) |
35 function onStateChange(event) { | 74 .then(function() { |
36 // Use setTimeout to ensure a fresh stack with no references to the worker. | 75 // Use setTimeout to ensure a fresh stack with no references to |
37 switch (event.target.state) { | 76 // the registration or worker. |
38 case 'activated': | |
39 setTimeout(unregister, 0); | |
40 break; | |
41 case 'redundant': | |
42 setTimeout(finish, 0); | 77 setTimeout(finish, 0); |
43 break; | 78 }) |
44 } | 79 .catch(function(error) { |
45 } | 80 testFailed(error.message || error.name || error); |
46 | 81 finishJSTest(); |
47 function unregister() { | |
48 // The worker has an event handler that can still receive the state change | |
49 // to 'redundant', so it shouldn't be collected yet. | |
50 gc(); | |
51 shouldBeFalse('swObservation.wasCollected'); | |
52 navigator.serviceWorker.unregister(scope).catch(function(error) { | |
53 testFailed('Could not unregister worker: ' + error); | |
54 finishJSTest(); | |
55 }); | 82 }); |
56 } | 83 } |
57 | 84 |
58 function finish() | 85 function finish() |
59 { | 86 { |
60 gc(); | 87 gc(); |
61 shouldBeTrue('swObservation.wasCollected'); | 88 shouldBeTrue('service_worker_observation.wasCollected'); |
| 89 shouldBeFalse('registration_observation.wasCollected'); |
62 finishJSTest(); | 90 finishJSTest(); |
63 } | 91 } |
64 </script> | 92 </script> |
OLD | NEW |