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@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev