Re: What changes to Web Messaging spec are proposed? [Was: Re: Using ArrayBuffer as payload for binary data to/from Web Workers]

On Tue, 21 Jun 2011, Jonas Sicking wrote:
> On Tue, Jun 21, 2011 at 12:39 AM, Ian Hickson <ian@hixie.ch> wrote:
> > On Mon, 20 Jun 2011, Jonas Sicking wrote:
> >>
> >> If data appears both in the .ports array and the .data property, then 
> >> people will be tempted to create protocols which only work if the 
> >> array buffer is transferred, i.e. if the receiver only looks in 
> >> .ports. I.e. people will likely end up with equally ugly solutions 
> >> like:
> >>
> >> postMessage('vend-reply', [createClone(arraybuffer)]);
> >
> > Yeah, that's a very good point.
> >
> > It really seems like part of the problem here is that ports and 
> > arrayBuffers are quite different (in that one will always want to be 
> > transferred, but for the other you might want to sometimes transfer 
> > and sometimes not).
> 
> I don't think we should worry too much about suboptimal syntax when 
> transferring ports. We can always add more syntax sugar later if people 
> think it's annoying. Better keep the initial version simple than to try 
> to guess which use cases will be the most common ones.

Keeping it simple is one of the reasons I don't want to require that 
authors list every port twice in order to send a port. (Sending a port is 
intended to be a common pattern, at least if the API is used as intended.)


So the current situation is as follows:

 - we want to be able to send structured data that is cloned.
 - we want the structured data to be able to contain arraybuffers and ports.
 - we want it to be possible for the author to opt-in to transferring
   specific arraybuffers rather than just cloning them.
 - we want the author to have to explicitly list the ports that are to be
   transferred because it would be easy to accidentally transfer one
   otherwise, and that would cause hard-to-find bugs (e.g. if the data 
   being cloned happened to contain debugging information that happened to 
   contain a reference to a port).
 - we don't want to require that authors list ports twice in the simple 
   case, since that's quite ugly
 - we don't want authors to design APIs where arraybuffers can only be 
   transferred and not copied; the receiving side should not be able to 
   influence the sending side's decision as to whether to clone or 
   transfer arraybuffers.

How about we just make postMessage() take the object to clone in the first 
argument, an array of objects to transfer in the second; on the other 
side, the author receives the object cloned, with anything listed in the 
array and in the structured data being transferred instead of cloned, and, 
in addition, in the event.ports array, a list of the ports that were given 
in the transfer array.

This has the advantage of being completely backwards-compatible.

So for example, on the sending side:

   postMessage(['copied', copiedArrayBuffer, transferredArrayBuffer,
                transferredPort1], // could be an object too
               [transferredArrayBuffer, transferredPort1,
                transferredPort2]);

...on the receiving side, the event has

   data == ['copied', newCopiedArrayBuffer, newTransferredArrayBuffer,  
            newTransferredPort1];
   ports == [newTransferredPort1, newTransferredPort2];

It's not going to win any design awards, but I think that boat has sailed 
for this particular API anyway, given the contraints we're operating under.

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

Received on Tuesday, 21 June 2011 18:08:16 UTC