[webkit-dev] Passing data structures through postMessage()

Drew Wilson atwilson at google.com
Thu Sep 10 17:29:37 PDT 2009


Good point - re-reviewing the Structured Clone spec, I see all kinds of
crazy stuff is cloneable now, so string/JSON may not be a particularly good
basis. It seems that we'll need to support File access from Workers, since
you can clone/send those objects over from page context.
I had expected that having a common serialization format would be useful,
but I agree - it probably is better to just send opaque objects around,
which might enable WebKit to send actual cloned object instances without
requiring any serialization, while chromium can do the serialization itself
when sending the data cross-process.

-atw

On Thu, Sep 10, 2009 at 5:21 PM, Maciej Stachowiak <mjs at apple.com> wrote:

>
> On Sep 10, 2009, at 3:12 PM, Chris Campbell wrote:
>
>  Hi All,
>>
>> I had it in mind to implement support for passing data structures
>> through postMessage() using the "structured clone" algorithm laid out
>> in the HTML5 spec:
>>
>> http://dev.w3.org/html5/spec/Overview.html#posting-messages
>> http://dev.w3.org/html5/spec/Overview.html#safe-passing-of-structured-data
>>
>> I've had some brief discussion with Dave Levin and Drew Wilson on
>> #chromium IRC about this, and have an approach in mind that follows
>> and elaborates on their suggestions, but there are still some holes in
>> it and I'd very much like input from people familiar with this area.
>>
>> Currently, there are several postMessage() handlers (in
>> MessagePort.idl, DOMWindow.idl, DedicatedWorkerContext.idl, and
>> Worker.idl), and they all take a DOMString for the message parameter.
>>
>> The general idea is to change that message parameter from a DOMString
>> to a new AttributeIterator type that allows walking of any sort of JS
>> structure/type.  AttributeIterator would essentially be an adapter to
>> translate native V8 or JSC JavaScript objects to an agnostic interface
>> suitable for walking the structure and serializing it.  I'm thinking
>> it would look something like this:
>>
>> interface AttributeIterator {
>>   bool isUndefined();
>>   bool isNull();
>>   bool isFalse();
>>   bool isTrue();
>>   bool isNumber();
>>   String getNumber();
>>   bool isString();
>>
>>   // ... cover the other types including Date, RegExp, ImageData,
>>   // File, FileData, and FileList ...
>>
>>   // Retrieve the key for the next property (for Objects and Arrays)
>>   String nextEnumerableProperty();
>>
>>   AttributeIterator getPropertyValue(key);
>> }
>>
>
> Some thoughts off the cuff:
>
> I think it would be better to write custom code for doing the cloning for
> each JS engine. For one thing, turning everything into a string is not
> necessarily the most efficient way to do things. It might be possible to
> clone the object graph more directly in a threadsafe way. Also, things like
> File and ImageData fundamentally can't be turned into a string (well
> ImageData can)
>
> Second, to be really agnostic about it, postMessage should take a generic
> Message object that has some methods that can be used to do the cross-thread
> clone without building in the assumption that it serializes to a string in
> the middle.
>
> Third, using a stateful iterator for this instead of an interface
> representing a value is not a great design. Iterators are not good when what
> you are traversing is in general a graph.
>
> Fourth, this doesn't give a way to detect if an object graph is not in fact
> legal to clone.
>
> It's kind of a shame that we have the baggage of multiple JavaScript
> engines to contend with. Trying to do things in a generic way will make this
> task needlessly more difficult.
>
> You may also want to get input on this from Oliver Hunt, who wrote the JSC
> JSON parse/stringify code; from past discussions I know has opinions on how
> cross-thread cloning should work.
>
>
>
>>
>> I'm also thinking that depending on compile-time flags, the
>> contstructor for AttributeIterator would either take a
>> v8::Handle<v8::Value> or JSC::JSvalue value.
>>
>> Then in each implementation of postMessage() the AttributeIterator
>> instance could be passed to the structured clone serializer, which
>> would return a string.  Thereafter, no changes would be required to
>> WebCore internals since they already pass strings around... until on
>> the receiving end we get to MessageEvent.data where we would do the
>> deserialization in a custom getter.
>>
>>
>> Open questions:
>>
>> (1) Is passing an AttributeIterator type into postMessage() really the
>> best way to go?  Drew mentioned that this might incur a bunch of ObjC
>> binding work on the JSC side...
>>
>> (2) Where should AttributeIterator live in the source tree?
>>
>> (3) Where should the serialization and deserialization routines live
>> in the source tree?
>>
>> (3) I haven't addressed the specifics of the serialized string format.
>> Plain JSON is not quite sufficient since it doesn't retain type
>> information for Date, RegExp, etc..  However, I'm not too worried
>> about coming up with a suitable format for this.
>>
>>
>> Comments, advice, admonitions welcome!  :)
>>
>
> In general I'm not sure this approach is workable. At the very least File,
> FileData, FileList and ImageData need to be passed as something other than
> strings. And I think the value of making the object graph traversal code
> generic while everything else is JS-engine-specific is pretty low. In
> addition, I do not think the proposed interface is adequate to implement the
> cloning algorithm.
>
> Regards,
> Maciej
>
>
>
> _______________________________________________
> webkit-dev mailing list
> webkit-dev at lists.webkit.org
> http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.webkit.org/pipermail/webkit-dev/attachments/20090910/e8750ebe/attachment.html>


More information about the webkit-dev mailing list