Re: postMessage is the new wtf

On Tue, Dec 13, 2011 at 3:30 PM, Charles Pritchard <chuck@jumis.com> wrote:

> On 12/13/11 11:11 AM, Dmitry Lomov wrote:
>
>>   worker.postMessage({p:port, ab:arrayBuffer}, [post, arrayBuffer])
>> work. Therefore this extension to postMessage semantics is both
>> backwards-compatible and consistent. On the receiving side, the 'ports'
>> property of event object will still contain only the message ports from the
>> transfer list, so that behavior is preserved as well.
>>
>
> What's the behavior if an array buffer or port is not on the
> transferrables list?
> For example: worker.postMessage({p:port, ab:arrayBuffer})
>

If a port is in the first argument but not listed in transfer,
DATA_CLONE_ERR will be thrown by the structured clone algorithm when it
encounters the MessagePort in step 3 of the internal structured clone
algorithm.

This doesn't happen when the port is listed for transfer, because the
MessagePort will already be in *memory* when step 1 encounters it ("If
input is the source object...").

What matters to users here is that structured clone itself is always a
const operation; it never modifies its arguments.  If you say
postMessage({obj: opaqueObject}), where opaqueObject is provided by a
third-party library, you never have to worry that postMessage (or
IndexedDB, or History, etc.) might modify the object and break the
library.  It can only modify things that you explicitly list in transfer.
This helps future API expansion as well: transfer support can be added to
more objects in the future, without breaking existing code by causing
unexpected new side-effects.

(ArrayBuffers will simply be copied by default, since they support
structured clone.)



> The clone example you posted makes sense:
>
> worker.postMessage({p:port, ab:arrayBuffer}, [post, arrayBuffer])
>
> If transferrables is supported, it'll ensure the vars are neutered and
> referenced appropriately, and if they aren't supported, it'll still pass a
> copy of array buffer through the message data.
>

Pre-Transferable implementations will throw here, since they only allow
MessagePort in MessagePortArray.  If you want to use transfer while falling
back to copies for old browsers, you'll need to jump a few extra hoops (eg.
filter objects that aren't instances of Transferable yourself).

-- 
Glenn Maynard

Received on Tuesday, 13 December 2011 21:11:56 UTC