Re: [ServiceWorker] Clients & postMessage (#609)

@Hixie some background:

A page can `postMessage` to a ServiceWorker via:

```js
navigator.serviceWorker.controller.postMessage("Hello");
```

`navigator.serviceWorker.controller` is the ServiceWorker instance controlling the page (and likely other pages/Workers/SharedWorkers). Posted messages land in `self.onmessage` in the ServiceWorker's global scope.

In the ServiceWorker, `self.clients` gives the ServiceWorker insight into clients on the origin, where clients are Windows, Workers and SharedWorkers. The current API allows:

```js
clients.matchAll().then(clients => {
  clients[0].postMessage("Hello");
});
```

…as a method for the ServiceWorker to communicate with a client. This is where there's disagreement. My thinking was, for windows, `client.postMessage` would land in `window.onmessage`, because a window client should behave like `WindowProxy` but be safe to use in a worker. @annevk disagrees (see https://github.com/slightlyoff/ServiceWorker/issues/609#issuecomment-71622477).

It means that `messageEvent.source` within `window.onmessage` would be an instance of `ServiceWorker` if the message was sent from a ServiceWorker. If libraries depended on `messageEvent.source` being a `WindowProxy`, things could break. This would only affect sites that already use a library with that assumption, then add ServiceWorker, then `postMessage` a client running that library. This would be revealed during development rather than on a live site, and we could monitor that as the feature moves through Canary/Dev/Beta.

If the client is a SharedWorker we don't currently have anywhere to land the message. I think we should just return the Worker/SharedWorker objects as clients, and the developer can communicate with them the standard way. Basically, we only need clients for windows because there isn't currently a window representation that can exist in a worker, `WindowClient` becomes that thing.

## Other possibilities

@annevk suggests dropping `postMessage` and instead relying on `BroadcastChannel` which Mozilla recently implemented. I'm fond of `BroadcastChannel`, but it doesn't allow communication with a specific client.

There's also the idea of stashing message ports within ServiceWorker registrations https://gist.github.com/mkruisselbrink/536632fcd99d45005064 - but this comes with all the GC observation of `PortCollection`, along with potential leaks if both ports are stashed. Plus it's pretty complicated compared to `client.postMessage`.

---
Reply to this email directly or view it on GitHub:
https://github.com/slightlyoff/ServiceWorker/issues/609#issuecomment-73222577

Received on Friday, 6 February 2015 11:21:51 UTC