[whatwg] onclose events for MessagePort

Ian Hickson ian at hixie.ch
Thu Jan 30 11:41:09 PST 2014

On Fri, 13 Dec 2013, Jonas Sicking wrote:
> On Fri, Dec 13, 2013 at 3:29 PM, Ian Hickson <ian at hixie.ch> wrote:
> > On Wed, 11 Dec 2013, Jonas Sicking wrote:
> >> No sync IPC needed. When a port is pinned, you send an async message 
> >> to the process which contains the page for the "other side". When 
> >> that process receives the message you check if the page is currently 
> >> being displayed.
> >>
> >> If the page has been completely torn down then you send a message 
> >> back saying that the page is dead and that the promise created during 
> >> pinning should be rejected.
> >>
> >> If the page is sitting in the bfcache, you remove it from the bfcache 
> >> and send a message back saying that the page is dead and that the 
> >> promise created during pinning should be rejected.
> >>
> >> If the page is displayed, then you add a flag indicating that if the 
> >> page is navigated away from, it should not go into the bfcache and 
> >> that we should send a signal to reject the promise.
> >>
> >> Obviously if the process had crashed before we were able to process 
> >> the event, you send a message back to reject the promise.
> >>
> >> The same thing is done when unpinning. You send a message to the 
> >> other side saying that it's getting unpinned.
> >
> > This means that it's possible to get a lock, have the other side 
> > navigate then go back, then have the other side receive the 
> > notification for the lock. It's this that you need blocking IPC to 
> > prevent. But I guess we could live with that just being possible.
> Indeed. The idea with bfcache is that going back/forward should be 
> largely transparent to the page itself. So I think it's fine that it's 
> transparent also to the page that's talking to it in this instance.
> Kicking the page out of bfcache isn't a goal in and of itself. The goal 
> is to prevent other pages from waiting unduly long for a message.

This basically boils down to being able to flip a switch on a MessagePort 
saying that the port should not be GC'ed and should prevent its owner's 
pages from being bfcached, right? I'm still very uncomfortable with this 
idea of preventing either of these. Having a way to prevent GC on objects 
that would otherwise get GC'ed seems like it would result in leaks, and 
preventing bfcache seems like it would defeat the entire bfcache idea 
(consider what happens if some ad networks start using shared workers to 
make obtaining and showing ads more efficient, and they communicate with 
the host pages with ports that they block bfcache on -- suddently large 
parts of the Web would have bfcache defeated).

> We could allow bfcaching here by introducing the discussed separate 
> features which allow the page to signal that it's fine with being 
> bfcached even though the error was signaled. That way if the page is 
> revived from bfcache it can send a message on the channel saying "I'm 
> back now" at which point they can resume communicating.

How would this work when a page has several libraries (e.g. ads, Facebook 
like button, Twitter tweet button), each talking to their shared worker, 
and each with different opinions about whether or not they can handle a 
bfcache situation?

> > [...] So you'd have:
> >
> >    port.onmessage - received a message
> >    port.onerror - other side crashed or was terminate()d
> >    port.onsuspend - other side went to sleep
> >    port.onresume - other side came back
> Wouldn't this expose GC behavior? If an unreferenced channel is GCed 
> before the page navigates then port.onsuspend is not fired. If the same 
> unreferenced channel is not GCed before the page navigates then 
> port.onsuspend is fired.


> Additionally as the only implementation of a bfcaching browser this is a 
> risky API. In all other browsers, once onsuspend has fired the channel 
> is dead and no events will fire.

Right, that's why I hadn't added support for this in the spec.

I really don't know what the right solution is here. I had originally 
added "onclose" to ports really early on, but we dropped it because it 
exposes GC. Fundamentlly, I think any solution we come up with here either 
has to expose GC or block GC, neither of which are a good idea. Same with 
the bfcache: every solution either has to expose the bfcache or prevent 
it, neither of which is a good idea.

So what can we do?

What the spec has now (MessagePort.onerror) only helps for the limited 
case of a process getting killed by the system; it doesn't help for any of 
the features of the Web platform like navigation, Worker.terminate(), etc.

Maybe the right thing here is for you (browser vendors) to experiment with 
different approaches to this, and for me to just spec whatever comes out 
of that.

Ian Hickson               U+1047E                )\._.,--....,'``.    fL
http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'

More information about the whatwg mailing list