Bug 1319334 - Resolve ready promise *after* updating registration.state properties. r=bkelly
authorCatalin Badea <catalin.badea392@gmail.com>
Tue, 22 Nov 2016 06:38:00 +0800
changeset 323930 1dcdef45d753e0fa011389e8713a50a7051d4342
parent 323929 2bbc7be933e2cd52fb1e328119075cf9aab50c5f
child 323931 dd83ff2a1d8595908a4da05b432d9cd08a7f59ec
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewersbkelly
bugs1319334
milestone53.0a1
Bug 1319334 - Resolve ready promise *after* updating registration.state properties. r=bkelly
dom/workers/ServiceWorkerRegistrationInfo.cpp
dom/workers/test/serviceworkers/test_worker_reference_gc_timeout.html
--- a/dom/workers/ServiceWorkerRegistrationInfo.cpp
+++ b/dom/workers/ServiceWorkerRegistrationInfo.cpp
@@ -235,20 +235,18 @@ ServiceWorkerRegistrationInfo::Activate(
   if (!mWaitingWorker) {
     return;
   }
 
   TransitionWaitingToActive();
 
   // FIXME(nsm): Unlink appcache if there is one.
 
+  // "Queue a task to fire a simple event named controllerchange..."
   RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
-  swm->CheckPendingReadyPromises();
-
-  // "Queue a task to fire a simple event named controllerchange..."
   nsCOMPtr<nsIRunnable> controllerChangeRunnable =
     NewRunnableMethod<RefPtr<ServiceWorkerRegistrationInfo>>(
       swm, &ServiceWorkerManager::FireControllerChange, this);
   NS_DispatchToMainThread(controllerChangeRunnable);
 
   nsCOMPtr<nsIRunnable> failRunnable =
     NewRunnableMethod<bool>(this,
                             &ServiceWorkerRegistrationInfo::FinishActivate,
@@ -314,16 +312,20 @@ ServiceWorkerRegistrationInfo::AsyncUpda
 {
   AssertIsOnMainThread();
   RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
   if (aTransition == Invalidate) {
     swm->InvalidateServiceWorkerRegistrationWorker(this, aWorker);
   } else {
     MOZ_ASSERT(aTransition == TransitionToNextState);
     swm->TransitionServiceWorkerRegistrationWorker(this, aWorker);
+
+    if (aWorker == WhichServiceWorker::WAITING_WORKER) {
+      swm->CheckPendingReadyPromises();
+    }
   }
 }
 
 void
 ServiceWorkerRegistrationInfo::UpdateRegistrationStateProperties(WhichServiceWorker aWorker,
                                                                  TransitionType aTransition)
 {
   AssertIsOnMainThread();
--- a/dom/workers/test/serviceworkers/test_worker_reference_gc_timeout.html
+++ b/dom/workers/test/serviceworkers/test_worker_reference_gc_timeout.html
@@ -23,34 +23,55 @@ SimpleTest.requestFlakyTimeout("Forcing 
 
 add_task(function setupPrefs() {
   return SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true],
   ]});
 });
 
-//var worker;
 add_task(function* test_worker_ref_gc() {
   let registration = yield navigator.serviceWorker.register(
     "lazy_worker.js", { scope: "./lazy_worker_scope_timeout"} )
     .then(function(registration) {
       SpecialPowers.exactGC();
       var worker = registration.installing;
       return new Promise(function(resolve) {
         worker.addEventListener('statechange', function() {
           info("state is " + worker.state + "\n");
           SpecialPowers.exactGC();
           if (worker.state === 'activated') {
             resolve(registration);
           }
         });
       });
     });
-
   ok(true, "Got activated event!");
 
   yield registration.unregister();
+});
+
+add_task(function* test_worker_ref_gc_ready_promise() {
+  let wait_active = navigator.serviceWorker.ready.then(function(reg) {
+    SpecialPowers.exactGC();
+    ok(reg.active, "Got active worker.");
+    ok(reg.active.state === "activating", "Worker is in activating state");
+    return new Promise(function(res) {
+      reg.active.onstatechange = function(e) {
+        reg.active.onstatechange = null;
+        ok(reg.active.state === "activated", "Worker was activated");
+        res();
+      }
+    });
+  });
+
+  let registration = yield navigator.serviceWorker.register(
+    "lazy_worker.js", { scope: "."} );
+  yield wait_active;
+  yield registration.unregister();
+});
+
+add_task(function* cleanup() {
   yield SpecialPowers.popPrefEnv();
 });
 </script>
 </body>
 </html>