Bug 1257977 Comment 12 Edit History

Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.

So spec-wise, where we are with the spec is:
- In [install](https://w3c.github.io/ServiceWorker/#install) in the spec the notable tasks / state updates are:
  - Step 4 invokes [Update Registration State](https://w3c.github.io/ServiceWorker/#update-registration-state) is invoked with (registration, "installing", a new worker that was created by [update which invoked install](https://w3c.github.io/ServiceWorker/#ref-for-install%E2%91%A1)).  This dispatches a task to all registration objects to set installing.  The worker rep comes from [get the service worker object](https://w3c.github.io/ServiceWorker/#get-the-service-worker-object) which uses the per-global [service worker object map](https://w3c.github.io/ServiceWorker/#environment-settings-object-service-worker-object-map) which follows a get-or-create idiom.
    - We do not update the ServiceWorker's state if its identity was already known!  Only if we are freshly creating the binding for the global in the map.  In this "installing" case, we generally expect the ServiceWorker to be freshly created because we have no "evaluating" slot on the registration, but it's conceivable it might be able to use the Clients API to postMessage a client and have its ServiceWorker binding created and exposed in some pathological situations we don't really try to enable.
    - Because this is a task, but because there is no event fired in this step, this change is notionally observable distinct from the next step, but I don't believe there's any requirement that the steps must be something that can be observed as distinct.  Like it's not clear there's any way the spec requires to be able to run a task after this task and before the task that will come from the next step.  This is notable because we explicitly folded the two steps together, with our registration being responsible for updating the registration and the ServiceWorker state.  (That is, [mozilla_dom::PServiceWorkerRegistration::UpdateState](https://searchfox.org/mozilla-central/rev/a215fbd85843a91fcd8fdc33aa9cd9a357403f35/dom/serviceworkers/PServiceWorkerRegistration.ipdl#35) does both, and [PServiceWorker](https://searchfox.org/mozilla-central/rev/a215fbd85843a91fcd8fdc33aa9cd9a357403f35/dom/serviceworkers/PServiceWorker.ipdl) is just a handle for calling PostMessage.
  - Step 5 invokes [Update Worker State](https://w3c.github.io/ServiceWorker/#update-worker-state) with (the new worker, "installing").  This dispatches a task to all globals to update the ServiceWorker iff it exists in the map and fires a "statechange" event.  As noted above, our implementation folds these together.  We also have some [support infrastructure with callbacks for the ready promise](https://searchfox.org/mozilla-central/rev/a215fbd85843a91fcd8fdc33aa9cd9a357403f35/dom/serviceworkers/ServiceWorkerContainer.cpp#655-660).
  - Step 7 resolves the job promise which will expose the new worker in the "installing" slot (and the registration and ServiceWorker are coherent since this happens after the 2 steps above))
  - Step 9 iterates over the globals and queues tasks to enumerate their registration objects and fire "updatefound" on them.
  - Step 11 queues firing the "install" event at the ServiceWorker.
- Our [mozilla::dom::ServiceWorkerUpdateJob::Install](https://searchfox.org/mozilla-central/rev/46d0387f0b582f00a5722c20d4e6b8693793631b/dom/serviceworkers/ServiceWorkerUpdateJob.cpp#464-495) implementation:
  -  Step 4 + 5: [Triggers the movement from evaluating to installing on the registration](https://searchfox.org/mozilla-central/rev/46d0387f0b582f00a5722c20d4e6b8693793631b/dom/serviceworkers/ServiceWorkerUpdateJob.cpp#474) (because we do have a concept of evaluating).  This ends up calling [mozilla::dom::ServiceWorkerRegistrationProxy::UpdateState](https://searchfox.org/mozilla-central/rev/a215fbd85843a91fcd8fdc33aa9cd9a357403f35/dom/serviceworkers/ServiceWorkerRegistrationProxy.cpp#126) on the main thread which bounces a runnable to call [mozilla::dom::ServiceWorkerRegistrationProxy::UpdateStateOnBGThread](https://searchfox.org/mozilla-central/rev/a215fbd85843a91fcd8fdc33aa9cd9a357403f35/dom/serviceworkers/ServiceWorkerRegistrationProxy.cpp#60) on PBackground to the relevant actor (one proxy and one runnable per one actor per global).
  - Step 7: [Invoke the result callbacks which should resolve the job promise](https://searchfox.org/mozilla-central/rev/46d0387f0b582f00a5722c20d4e6b8693793631b/dom/serviceworkers/ServiceWorkerUpdateJob.cpp#476-477).
  - Step 9: [Initiate the firing of updatefound](https://searchfox.org/mozilla-central/rev/46d0387f0b582f00a5722c20d4e6b8693793631b/dom/serviceworkers/ServiceWorkerUpdateJob.cpp#479-481).
    - We do a problematic thing in [mozilla::dom::ServiceWorkerRegistration::MaybeDispatchUpdateFoundRunnable](https://searchfox.org/mozilla-central/rev/a215fbd85843a91fcd8fdc33aa9cd9a357403f35/dom/serviceworkers/ServiceWorkerRegistration.cpp#546-560) where we explicitly delay the notification by a turn of the event loop.  I believe this is the result of the cleanup in https://phabricator.services.mozilla.com/D13368 leaving an event loop delay mitigation that made sense when we were triggering the "updatefound" notification off of the step 7 promise being resolved because we needed "updatefound" to be its own task that would come after the promise was resolved.  It is likely the delay ceased to make sense at that time, although there were child intercept complications that made this all much harder to reason about (and not of our modern searchfox niceties).
  - Step 11: [We fire the lifecycle event](https://searchfox.org/mozilla-central/rev/46d0387f0b582f00a5722c20d4e6b8693793631b/dom/serviceworkers/ServiceWorkerUpdateJob.cpp#488-491).
    - Note that until the approved patches on bug 1672493 land, this does follow a different propagation path than the previous steps since there is a bounce to the content process main thread, but it will have been much less race-prone since we moved to a single IPC channel per-process-pair and the "install" event is the one that's subject to additional delays, and it's already the last thing in that sequence and establishes a synchronizing data dependency on the job queue state machine advancing, so the subsequent state transitions can't happen until it is observed on the worker thread.
Analysis of the test failure / ordering going on:
- In [install](https://w3c.github.io/ServiceWorker/#install) in the spec the notable tasks / state updates are:
  - Step 4 invokes [Update Registration State](https://w3c.github.io/ServiceWorker/#update-registration-state) is invoked with (registration, "installing", a new worker that was created by [update which invoked install](https://w3c.github.io/ServiceWorker/#ref-for-install%E2%91%A1)).  This dispatches a task to all registration objects to set installing.  The worker rep comes from [get the service worker object](https://w3c.github.io/ServiceWorker/#get-the-service-worker-object) which uses the per-global [service worker object map](https://w3c.github.io/ServiceWorker/#environment-settings-object-service-worker-object-map) which follows a get-or-create idiom.
    - We do not update the ServiceWorker's state if its identity was already known!  Only if we are freshly creating the binding for the global in the map.  In this "installing" case, we generally expect the ServiceWorker to be freshly created because we have no "evaluating" slot on the registration, but it's conceivable it might be able to use the Clients API to postMessage a client and have its ServiceWorker binding created and exposed in some pathological situations we don't really try to enable.
    - Because this is a task, but because there is no event fired in this step, this change is notionally observable distinct from the next step, but I don't believe there's any requirement that the steps must be something that can be observed as distinct.  Like it's not clear there's any way the spec requires to be able to run a task after this task and before the task that will come from the next step.  This is notable because we explicitly folded the two steps together, with our registration being responsible for updating the registration and the ServiceWorker state.  (That is, [mozilla_dom::PServiceWorkerRegistration::UpdateState](https://searchfox.org/mozilla-central/rev/a215fbd85843a91fcd8fdc33aa9cd9a357403f35/dom/serviceworkers/PServiceWorkerRegistration.ipdl#35) does both, and [PServiceWorker](https://searchfox.org/mozilla-central/rev/a215fbd85843a91fcd8fdc33aa9cd9a357403f35/dom/serviceworkers/PServiceWorker.ipdl) is just a handle for calling PostMessage.
  - Step 5 invokes [Update Worker State](https://w3c.github.io/ServiceWorker/#update-worker-state) with (the new worker, "installing").  This dispatches a task to all globals to update the ServiceWorker iff it exists in the map and fires a "statechange" event.  As noted above, our implementation folds these together.  We also have some [support infrastructure with callbacks for the ready promise](https://searchfox.org/mozilla-central/rev/a215fbd85843a91fcd8fdc33aa9cd9a357403f35/dom/serviceworkers/ServiceWorkerContainer.cpp#655-660).
  - Step 7 resolves the job promise which will expose the new worker in the "installing" slot (and the registration and ServiceWorker are coherent since this happens after the 2 steps above))
  - Step 9 iterates over the globals and queues tasks to enumerate their registration objects and fire "updatefound" on them.
  - Step 11 queues firing the "install" event at the ServiceWorker.
- Our [mozilla::dom::ServiceWorkerUpdateJob::Install](https://searchfox.org/mozilla-central/rev/46d0387f0b582f00a5722c20d4e6b8693793631b/dom/serviceworkers/ServiceWorkerUpdateJob.cpp#464-495) implementation:
  -  Step 4 + 5: [Triggers the movement from evaluating to installing on the registration](https://searchfox.org/mozilla-central/rev/46d0387f0b582f00a5722c20d4e6b8693793631b/dom/serviceworkers/ServiceWorkerUpdateJob.cpp#474) (because we do have a concept of evaluating).  This ends up calling [mozilla::dom::ServiceWorkerRegistrationProxy::UpdateState](https://searchfox.org/mozilla-central/rev/a215fbd85843a91fcd8fdc33aa9cd9a357403f35/dom/serviceworkers/ServiceWorkerRegistrationProxy.cpp#126) on the main thread which bounces a runnable to call [mozilla::dom::ServiceWorkerRegistrationProxy::UpdateStateOnBGThread](https://searchfox.org/mozilla-central/rev/a215fbd85843a91fcd8fdc33aa9cd9a357403f35/dom/serviceworkers/ServiceWorkerRegistrationProxy.cpp#60) on PBackground to the relevant actor (one proxy and one runnable per one actor per global).
  - Step 7: [Invoke the result callbacks which should resolve the job promise](https://searchfox.org/mozilla-central/rev/46d0387f0b582f00a5722c20d4e6b8693793631b/dom/serviceworkers/ServiceWorkerUpdateJob.cpp#476-477).
  - Step 9: [Initiate the firing of updatefound](https://searchfox.org/mozilla-central/rev/46d0387f0b582f00a5722c20d4e6b8693793631b/dom/serviceworkers/ServiceWorkerUpdateJob.cpp#479-481).
    - We do a problematic thing in [mozilla::dom::ServiceWorkerRegistration::MaybeDispatchUpdateFoundRunnable](https://searchfox.org/mozilla-central/rev/a215fbd85843a91fcd8fdc33aa9cd9a357403f35/dom/serviceworkers/ServiceWorkerRegistration.cpp#546-560) where we explicitly delay the notification by a turn of the event loop.  I believe this is the result of the cleanup in https://phabricator.services.mozilla.com/D13368 leaving an event loop delay mitigation that made sense when we were triggering the "updatefound" notification off of the step 7 promise being resolved because we needed "updatefound" to be its own task that would come after the promise was resolved.  It is likely the delay ceased to make sense at that time, although there were child intercept complications that made this all much harder to reason about (and not of our modern searchfox niceties).
  - Step 11: [We fire the lifecycle event](https://searchfox.org/mozilla-central/rev/46d0387f0b582f00a5722c20d4e6b8693793631b/dom/serviceworkers/ServiceWorkerUpdateJob.cpp#488-491).
    - Note that until the approved patches on bug 1672493 land, this does follow a different propagation path than the previous steps since there is a bounce to the content process main thread, but it will have been much less race-prone since we moved to a single IPC channel per-process-pair and the "install" event is the one that's subject to additional delays, and it's already the last thing in that sequence and establishes a synchronizing data dependency on the job queue state machine advancing, so the subsequent state transitions can't happen until it is observed on the worker thread.
Analysis of the test failure / ordering going on:
- In [install](https://w3c.github.io/ServiceWorker/#install) in the spec the notable tasks / state updates are:
  - Step 4 invokes [Update Registration State](https://w3c.github.io/ServiceWorker/#update-registration-state) is invoked with (registration, "installing", a new worker that was created by [update which invoked install](https://w3c.github.io/ServiceWorker/#ref-for-install%E2%91%A1)).  This dispatches a task to all registration objects to set installing.  The worker rep comes from [get the service worker object](https://w3c.github.io/ServiceWorker/#get-the-service-worker-object) which uses the per-global [service worker object map](https://w3c.github.io/ServiceWorker/#environment-settings-object-service-worker-object-map) which follows a get-or-create idiom.
    - We do not update the ServiceWorker's state if its identity was already known!  Only if we are freshly creating the binding for the global in the map.  In this "installing" case, we generally expect the ServiceWorker to be freshly created because we have no "evaluating" slot on the registration, but it's conceivable it might be able to use the Clients API to postMessage a client and have its ServiceWorker binding created and exposed in some pathological situations we don't really try to enable.
    - Because this is a task, but because there is no event fired in this step, this change is notionally observable distinct from the next step, but I don't believe there's any requirement that the steps must be something that can be observed as distinct.  Like it's not clear there's any way the spec requires to be able to run a task after this task and before the task that will come from the next step.  This is notable because we explicitly folded the two steps together, with our registration being responsible for updating the registration and the ServiceWorker state.  (That is, [mozilla_dom::PServiceWorkerRegistration::UpdateState](https://searchfox.org/mozilla-central/rev/a215fbd85843a91fcd8fdc33aa9cd9a357403f35/dom/serviceworkers/PServiceWorkerRegistration.ipdl#35) does both, and [PServiceWorker](https://searchfox.org/mozilla-central/rev/a215fbd85843a91fcd8fdc33aa9cd9a357403f35/dom/serviceworkers/PServiceWorker.ipdl) is just a handle for calling PostMessage.
  - Step 5 invokes [Update Worker State](https://w3c.github.io/ServiceWorker/#update-worker-state) with (the new worker, "installing").  This dispatches a task to all globals to update the ServiceWorker iff it exists in the map and fires a "statechange" event.  As noted above, our implementation folds these together.  We also have some [support infrastructure with callbacks for the ready promise](https://searchfox.org/mozilla-central/rev/a215fbd85843a91fcd8fdc33aa9cd9a357403f35/dom/serviceworkers/ServiceWorkerContainer.cpp#655-660).
  - Step 7 resolves the job promise which will expose the new worker in the "installing" slot (and the registration and ServiceWorker are coherent since this happens after the 2 steps above))
  - Step 9 iterates over the globals and queues tasks to enumerate their registration objects and fire "updatefound" on them.
  - Step 11 queues firing the "install" event at the ServiceWorker.
- Our [mozilla::dom::ServiceWorkerUpdateJob::Install](https://searchfox.org/mozilla-central/rev/46d0387f0b582f00a5722c20d4e6b8693793631b/dom/serviceworkers/ServiceWorkerUpdateJob.cpp#464-495) implementation:
  -  Step 4 + 5: [Triggers the movement from evaluating to installing on the registration](https://searchfox.org/mozilla-central/rev/46d0387f0b582f00a5722c20d4e6b8693793631b/dom/serviceworkers/ServiceWorkerUpdateJob.cpp#474) (because we do have a concept of evaluating).  This ends up calling [mozilla::dom::ServiceWorkerRegistrationProxy::UpdateState](https://searchfox.org/mozilla-central/rev/a215fbd85843a91fcd8fdc33aa9cd9a357403f35/dom/serviceworkers/ServiceWorkerRegistrationProxy.cpp#126) on the main thread which bounces a runnable to call [mozilla::dom::ServiceWorkerRegistrationProxy::UpdateStateOnBGThread](https://searchfox.org/mozilla-central/rev/a215fbd85843a91fcd8fdc33aa9cd9a357403f35/dom/serviceworkers/ServiceWorkerRegistrationProxy.cpp#60) on PBackground to the relevant actor (one proxy and one runnable per one actor per global).
  - Step 7: [Invoke the result callbacks which should resolve the job promise](https://searchfox.org/mozilla-central/rev/46d0387f0b582f00a5722c20d4e6b8693793631b/dom/serviceworkers/ServiceWorkerUpdateJob.cpp#476-477).
  - Step 9: [Initiate the firing of updatefound](https://searchfox.org/mozilla-central/rev/46d0387f0b582f00a5722c20d4e6b8693793631b/dom/serviceworkers/ServiceWorkerUpdateJob.cpp#479-481).
    - We do a problematic thing in [mozilla::dom::ServiceWorkerRegistration::MaybeDispatchUpdateFoundRunnable](https://searchfox.org/mozilla-central/rev/a215fbd85843a91fcd8fdc33aa9cd9a357403f35/dom/serviceworkers/ServiceWorkerRegistration.cpp#546-560) where we explicitly delay the notification by a turn of the event loop.
    - There's a somewhat interesting history here.  :bkelly's bug 1462772 gave us the ServiceWorkerRegistration-driven information propagation and then bug 1471929 gave us updatefound logic handling which intentionally diverged from the spec because of the inherent async update problem where parent-process APIs like getRegistrations() provide non-self-updating snapshots that require a roundtrip to get updates for, with us inferring when we should generate an updatefound event.  (Noting that a number of IPC improvements since then make it much more feasible to eliminate the need for the roundtrip.)  Then :mrbkap's bug 1510809 implementation brought back the explicit updatefound notification but the cleanup in https://phabricator.services.mozilla.com/D13368 left an event loop delay that made sense when we were triggering the "updatefound" notification off of the step 7 promise being resolved because we needed "updatefound" to be its own task that would come after the promise was resolved.  It is likely the delay ceased to make sense at that time, although there were child intercept complications that made this all much harder to reason about (and not of our modern searchfox niceties).
    - I believe we still do probably need the [updatefound inference logic](https://searchfox.org/mozilla-central/rev/a215fbd85843a91fcd8fdc33aa9cd9a357403f35/dom/serviceworkers/ServiceWorkerRegistration.cpp#579-582) for now.
  - Step 11: [We fire the lifecycle event](https://searchfox.org/mozilla-central/rev/46d0387f0b582f00a5722c20d4e6b8693793631b/dom/serviceworkers/ServiceWorkerUpdateJob.cpp#488-491).
    - Note that until the approved patches on bug 1672493 land, this does follow a different propagation path than the previous steps since there is a bounce to the content process main thread, but it will have been much less race-prone since we moved to a single IPC channel per-process-pair and the "install" event is the one that's subject to additional delays, and it's already the last thing in that sequence and establishes a synchronizing data dependency on the job queue state machine advancing, so the subsequent state transitions can't happen until it is observed on the worker thread.
Analysis of the test failure / ordering going on:
- In [install](https://w3c.github.io/ServiceWorker/#install) in the spec the notable tasks / state updates are:
  - Step 4 invokes [Update Registration State](https://w3c.github.io/ServiceWorker/#update-registration-state) is invoked with (registration, "installing", a new worker that was created by [update which invoked install](https://w3c.github.io/ServiceWorker/#ref-for-install%E2%91%A1)).  This dispatches a task to all registration objects to set installing.  The worker rep comes from [get the service worker object](https://w3c.github.io/ServiceWorker/#get-the-service-worker-object) which uses the per-global [service worker object map](https://w3c.github.io/ServiceWorker/#environment-settings-object-service-worker-object-map) which follows a get-or-create idiom.
    - We do not update the ServiceWorker's state if its identity was already known!  Only if we are freshly creating the binding for the global in the map.  In this "installing" case, we generally expect the ServiceWorker to be freshly created because we have no "evaluating" slot on the registration, but it's conceivable it might be able to use the Clients API to postMessage a client and have its ServiceWorker binding created and exposed in some pathological situations we don't really try to enable.
    - Because this is a task, but because there is no event fired in this step, this change is notionally observable distinct from the next step, but I don't believe there's any requirement that the steps must be something that can be observed as distinct.  Like it's not clear there's any way the spec requires to be able to run a task after this task and before the task that will come from the next step.  This is notable because we explicitly folded the two steps together, with our registration being responsible for updating the registration and the ServiceWorker state.  (That is, [mozilla_dom::PServiceWorkerRegistration::UpdateState](https://searchfox.org/mozilla-central/rev/a215fbd85843a91fcd8fdc33aa9cd9a357403f35/dom/serviceworkers/PServiceWorkerRegistration.ipdl#35) does both, and [PServiceWorker](https://searchfox.org/mozilla-central/rev/a215fbd85843a91fcd8fdc33aa9cd9a357403f35/dom/serviceworkers/PServiceWorker.ipdl) is just a handle for calling PostMessage.
  - Step 5 invokes [Update Worker State](https://w3c.github.io/ServiceWorker/#update-worker-state) with (the new worker, "installing").  This dispatches a task to all globals to update the ServiceWorker iff it exists in the map and fires a "statechange" event.  As noted above, our implementation folds these together.  We also have some [support infrastructure with callbacks for the ready promise](https://searchfox.org/mozilla-central/rev/a215fbd85843a91fcd8fdc33aa9cd9a357403f35/dom/serviceworkers/ServiceWorkerContainer.cpp#655-660).
  - Step 7 resolves the job promise which will expose the new worker in the "installing" slot (and the registration and ServiceWorker are coherent since this happens after the 2 steps above))
  - Step 9 iterates over the globals and queues tasks to enumerate their registration objects and fire "updatefound" on them.
  - Step 11 queues firing the "install" event at the ServiceWorker.
- Our [mozilla::dom::ServiceWorkerUpdateJob::Install](https://searchfox.org/mozilla-central/rev/46d0387f0b582f00a5722c20d4e6b8693793631b/dom/serviceworkers/ServiceWorkerUpdateJob.cpp#464-495) implementation:
  -  Step 4 + 5: [Triggers the movement from evaluating to installing on the registration](https://searchfox.org/mozilla-central/rev/46d0387f0b582f00a5722c20d4e6b8693793631b/dom/serviceworkers/ServiceWorkerUpdateJob.cpp#474) (because we do have a concept of evaluating).  This ends up calling [mozilla::dom::ServiceWorkerRegistrationProxy::UpdateState](https://searchfox.org/mozilla-central/rev/a215fbd85843a91fcd8fdc33aa9cd9a357403f35/dom/serviceworkers/ServiceWorkerRegistrationProxy.cpp#126) on the main thread which bounces a runnable to call [mozilla::dom::ServiceWorkerRegistrationProxy::UpdateStateOnBGThread](https://searchfox.org/mozilla-central/rev/a215fbd85843a91fcd8fdc33aa9cd9a357403f35/dom/serviceworkers/ServiceWorkerRegistrationProxy.cpp#60) on PBackground to the relevant actor (one proxy and one runnable per one actor per global).
  - Step 7: [Invoke the result callbacks which should resolve the job promise](https://searchfox.org/mozilla-central/rev/46d0387f0b582f00a5722c20d4e6b8693793631b/dom/serviceworkers/ServiceWorkerUpdateJob.cpp#476-477).
  - Step 9: [Initiate the firing of updatefound](https://searchfox.org/mozilla-central/rev/46d0387f0b582f00a5722c20d4e6b8693793631b/dom/serviceworkers/ServiceWorkerUpdateJob.cpp#479-481).
    - We do a problematic thing in [mozilla::dom::ServiceWorkerRegistration::MaybeDispatchUpdateFoundRunnable](https://searchfox.org/mozilla-central/rev/a215fbd85843a91fcd8fdc33aa9cd9a357403f35/dom/serviceworkers/ServiceWorkerRegistration.cpp#546-560) where we explicitly delay the notification by a turn of the event loop.
      - There's a somewhat interesting history here.  :bkelly's bug 1462772 gave us the ServiceWorkerRegistration-driven information propagation and then bug 1471929 gave us updatefound logic handling which intentionally diverged from the spec because of the inherent async update problem where parent-process APIs like getRegistrations() provide non-self-updating snapshots that require a roundtrip to get updates for, with us inferring when we should generate an updatefound event.  (Noting that a number of IPC improvements since then make it much more feasible to eliminate the need for the roundtrip.)  Then :mrbkap's bug 1510809 implementation brought back the explicit updatefound notification but the cleanup in https://phabricator.services.mozilla.com/D13368 left an event loop delay that made sense when we were triggering the "updatefound" notification off of the step 7 promise being resolved because we needed "updatefound" to be its own task that would come after the promise was resolved.  It is likely the delay ceased to make sense at that time, although there were child intercept complications that made this all much harder to reason about (and not of our modern searchfox niceties).
      - I believe we still do probably need the [updatefound inference logic](https://searchfox.org/mozilla-central/rev/a215fbd85843a91fcd8fdc33aa9cd9a357403f35/dom/serviceworkers/ServiceWorkerRegistration.cpp#579-582) for now.
  - Step 11: [We fire the lifecycle event](https://searchfox.org/mozilla-central/rev/46d0387f0b582f00a5722c20d4e6b8693793631b/dom/serviceworkers/ServiceWorkerUpdateJob.cpp#488-491).
    - Note that until the approved patches on bug 1672493 land, this does follow a different propagation path than the previous steps since there is a bounce to the content process main thread, but it will have been much less race-prone since we moved to a single IPC channel per-process-pair and the "install" event is the one that's subject to additional delays, and it's already the last thing in that sequence and establishes a synchronizing data dependency on the job queue state machine advancing, so the subsequent state transitions can't happen until it is observed on the worker thread.

Back to Bug 1257977 Comment 12