Re: Custom element design with ES6 classes and Element constructors

2015-01-14 Thread Dmitry Lomov
On Thu, Jan 15, 2015 at 5:11 AM, Yehuda Katz wyc...@gmail.com wrote:

 On Wed, Jan 14, 2015 at 3:47 PM, Domenic Denicola d...@domenic.me wrote:

 I had a chat with Dmitry Lomov (V8 team/TC39, helped shape the new ES6
 classes design, CC'ed). His perspective was helpful. He suggested a way of
 evolving the current createdCallback design that I think makes it more
 palatable, and allows us to avoid all of the teeth-gnashing we've been
 doing in this thread.

 - Define a default constructor for HTMLElement that includes something
 like:

   ```js
   const createdCallback = this.createdCallback;
   if (typeof createdCallback === function) {
 createdCallback();
   }
   ```

 - Detect whether the constructor passed to document.registerElement is
 the default ES class constructor or not. (By default, classes generate a
 constructor like `constructor(...args) { super(...args); }`.) If it is not
 the default constructor, i.e. if an author tried to supply one, throw an
 error. This functionality doesn't currently exist in ES, but it exists in
 V8 and seems like a useful addition to ES (e.g. as
 `Reflect.isDefaultConstructor`).


 This seems useful to me too. Something is nagging me about it though, as
 if there's a better way to help people with this use-case, but I'm not sure
 what.


 - Define the HTMLElement constructor to be smart enough to work without
 any arguments. It could do this by e.g. looking up `new.target` in the
 registry. I can prototype this in
 https://github.com/domenic/element-constructors.


 Isn't this at least a little future-hostile to things like `new
 MyElement(attrs)`? Is there a way we could get back to that in the future,
 in your mind?


If this is what is desired, HTMLElement can pass all its arguments to
createdCallback, i.e. call createdCallback(...args) in its constructor.

Since default constructors pass all their arguments upstream,
   new MyElement(attrs)
will pass attrs as arguments to HTMLElement constructor. HTMLElement
constructor needs no arguments itself, so it will pass all of those to
MyElement's createdCallback.




 With these tweaks, the syntax for registering an element becomes:

 ```js
 class MyEl extends HTMLElement {
   createdCallback() {
 // initialization code goes here
   }
 }

 document.registerElement(my-el, MyEl);
 ```

 Note how we don't need to save the return value of
 `document.registerElement`. `new MyEl()` still works, since it just calls
 the default `HTMLElement` constructor. (It can get its tag name by looking
 up `new.target === MyEl` in the custom element registry.) And, `new MyEl()`
 is equivalent to the parse-then-upgrade dance, since parsing corresponds to
 the main body of the HTMLElement constructor, and upgrading corresponds to
 proto-munging plus calling `this.createdCallback()`.

 Compare this to the ideal syntax that we've been searching for a way to
 make work throughout this thread:

 ```js
 class MyEl extends HTMLElement {
   constructor() {
 super();
 // initialization code goes here
   }
 }

 document.registerElement(my-el, MyEl);
 ```

 It's arguable just as good. You can't use the normal constructor
 mechanism, which feels sad. But let's talk about that.


 I think this works *perfectly* (kudos!)

Thanks!


 as long as we don't want to support constructor args being sent to
 readyCallback.


It seems to me this can still be supported, if I understand correctly what
do you want to to do.

Dmitry


 As a framework hook, that seems totally fine with me.



 Whenever you're working within a framework, be it Rails or ASP.NET or
 Polymer or the DOM, sometimes the extension mechanism for the framework
 is to allow you to derive from a given base class. When you do so, there's
 a contract of what methods you implement, what methods you *don't*
 override, and so on.


 Indeed. I've working on both Rails and Ember, and in both cases, it's *very
 rare* to subclass from the internal constructor. There's usually a hook
 (or event) API that subclasses can use so that the superclass
 implementation can provide a more ergonomic API to implementations.


 When doing this kind of base-class extension, you're implementing a
 specific protocol that the framework tells you to, and you don't have
 complete freedom. So, it seems pretty reasonable if you're working within a
 framework that says, you must not override the constructor; that's my
 domain. Instead, I've provided a protocol for how you can do
 initialization. Especially for a framework as complicated and full of
 initialization issues as the DOM.


 Agreed.


 This design seems pretty nice to me. It means we can get upgrading
 (which, a few people have emphasized, is key in an ES6 modules world),


 Can you say more about why same-identity upgrading is critical to the
 design (as opposed to dom-mutation upgrading)? I asked up-thread but didn't
 get any takers.


 we don't need to generate new constructors, and we can still use class
 syntax without it becoming just

Re: postMessage is the new wtf

2011-12-13 Thread Dmitry Lomov
Hi Rick,
here are some clarifications.

There were many (long!) discussions on public-webapps about the new
signature for postMessage:
http://lists.w3.org/Archives/Public/public-webapps/2011AprJun/thread.html
http://lists.w3.org/Archives/Public/public-webapps/2011AprJun/0304.html
http://lists.w3.org/Archives/Public/public-webapps/2011AprJun/0805.html
http://lists.w3.org/Archives/Public/public-webapps/2011AprJun/0985.html

window.webkitPostMessage(msg, transferables) does not really exist (it is
an error in the blog post, and I am told the post will be amended). What
exists is window.webkitPostMessage(msg, targetOrigin, transferables).

Regarding second argument to worker.(webkit)postMessage, this is the new
spec for it:
http://www.whatwg.org/specs/web-apps/current-work/multipage/workers.html#dedicated-workers-and-the-dedicatedworkerglobalscope-interface
.

The spec mandates 'void postMessage(any message, optional
sequenceTransferable transfer)'. Transferable includes both MessagePorts
and ArrayBuffers, so in the new spec the transfer argument to postMessage
may be a mix of both types, and a backwards-compat extension to what we had
before (sequenceMessagePort aka MessagePortArray). Note that message
ports got an additional change in semantics, and can now be mentioned in
the message as well - both
   worker.postMessage({p:port}, [port])
and
   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.

I hope this helps,
Thanks,
Dmitry



On Tue, Dec 13, 2011 at 8:24 AM, Rick Waldron waldron.r...@gmail.comwrote:

 Following the recent blog post
 http://updates.html5rocks.com/2011/12/Transferable-Objects-Lightning-Fastand 
 subsequent Twitter discussion regarding changes to the parameter list
 of:

 Worker.prototype.postMessage( message [, transfer ] ) [1]

 DedicatedWorkerGlobalScope void 
 postMessagehttp://dev.w3.org/html5/workers/#dom-dedicatedworkerglobalscope-postmessage(any
 message, optional sequenceTransferable transfer) [2][3]


 I'm unable to find documentation or discussion that would clarify the
 rationale of over-using and over-loading the postMessage Identifier;
 considering the the blog cited above shows this example:

 [window|worker].webkitPostMessage(uInt8Array.buffer, [uInt8Array.buffer]);

  which conflicts with:

 window.postMessage(message, targetOrigin [, transfer ]) [4][5]

 and they both conflict with:

 DedicatedWorkerGlobalScope : WorkerGlobalScope ...
  void postMessage(in any message, in optional MessagePortArray ports); [6]

 Currently, passing a second arg to worker.postMessage(), that is not a
 MessagePortArray raises
 Uncaught TypeError: MessagePortArray argument must contain only
 MessagePorts in Chrome and Could not get domain warning in Firefox.


 Any reasonable clarification would be greatly appreciated.

 Thanks in advance

 Rick


 [1]
 http://www.whatwg.org/specs/web-apps/current-work/multipage/workers.html#dedicated-workers-and-the-worker-interface

 [2]
 http://www.whatwg.org/specs/web-apps/current-work/multipage/workers.html#dedicated-workers-and-the-dedicatedworkerglobalscope-interface

 [3]
 http://dev.w3.org/html5/workers/#dedicated-workers-and-the-dedicatedworkerglobalscope-interface

 [4]
 http://www.whatwg.org/specs/web-apps/current-work/multipage/web-messaging.html#web-messaging

 [5]
 http://www.whatwg.org/specs/web-apps/current-work/multipage/web-messaging.html#posting-messages

 [6] PREVIOUS SPECIFICATION STATE!!!
 http://www.w3.org/TR/2011/WD-workers-20110208/#dedicated-workers-and-the-dedicatedworkerglobalscope-interface



Re: postMessage is the new wtf

2011-12-13 Thread Dmitry Lomov
(resending to list - Rick, sorry if you get this twice)

On Tue, Dec 13, 2011 at 11:59 AM, Rick Waldron waldron.r...@gmail.com
 wrote:



 On Tue, Dec 13, 2011 at 2:11 PM, Dmitry Lomov dslo...@chromium.org
  wrote:


 window.webkitPostMessage(msg, transferables) does not really exist (it is
 an error in the blog post, and I am told the post will be amended). What
 exists is window.webkitPostMessage(msg, targetOrigin, transferables).


 This supports the subject line postMessage is the new wtf


You are obviously entitled to your own opinions, but folks were working
hard to make sure that changes to the spec result in API that is both makes
sense in its final form and does not break the Web.



 The spec mandates 'void postMessage(any message, optional
 sequenceTransferable transfer)'. Transferable includes both MessagePorts
 and ArrayBuffers, so in the new spec the transfer argument to postMessage
 may be a mix of both types, and a backwards-compat extension to what we had
 before (sequenceMessagePort aka MessagePortArray). Note that message
 ports got an additional change in semantics, and can now be mentioned in
 the message as well - both

worker.postMessage({p:port}, [port])
 and
worker.postMessage({p:port, ab:arrayBuffer}, [post, arrayBuffer])
 work. Therefore this extension to postMessage semantics is both
 backwards-compatible and consistent.


 Can you provide a reference for this? I'm unable to locate anything that
 covers these semantics.


A spec for structured cloning algorithm (ready-for-implementations state):
http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#safe-passing-of-structured-data
A spec for typed array tarnsfer (strawman state):
http://www.khronos.org/registry/typedarray/specs/latest/#9

(I agree it is not super easy to find these, but all this is bleeding-edge
still - when dust settles, I am sure there will be more blog posts,
articles and all that jazz)

Thanks!

Dmitry




 On Tue, Dec 13, 2011 at 8:24 AM, Rick Waldron waldron.r...@gmail.comwrote:

 Following the recent blog post
 http://updates.html5rocks.com/2011/12/Transferable-Objects-Lightning-Fastand
  subsequent Twitter discussion regarding changes to the parameter list
 of:

 Worker.prototype.postMessage( message [, transfer ] ) [1]

 DedicatedWorkerGlobalScope void 
 postMessagehttp://dev.w3.org/html5/workers/#dom-dedicatedworkerglobalscope-postmessage(any
 message, optional sequenceTransferable transfer) [2][3]


 I'm unable to find documentation or discussion that would clarify the
 rationale of over-using and over-loading the postMessage Identifier;
 considering the the blog cited above shows this example:

 [window|worker].webkitPostMessage(uInt8Array.buffer, [uInt8Array.buffer
 ]);

  which conflicts with:

 window.postMessage(message, targetOrigin [, transfer ]) [4][5]

 and they both conflict with:

 DedicatedWorkerGlobalScope : WorkerGlobalScope ...
  void postMessage(in any message, in optional MessagePortArray ports);
 [6]

 Currently, passing a second arg to worker.postMessage(), that is not a
 MessagePortArray raises
 Uncaught TypeError: MessagePortArray argument must contain only
 MessagePorts in Chrome and Could not get domain warning in Firefox.


 Any reasonable clarification would be greatly appreciated.

 Thanks in advance

 Rick


 [1]
 http://www.whatwg.org/specs/web-apps/current-work/multipage/workers.html#dedicated-workers-and-the-worker-interface

 [2]
 http://www.whatwg.org/specs/web-apps/current-work/multipage/workers.html#dedicated-workers-and-the-dedicatedworkerglobalscope-interface

 [3]
 http://dev.w3.org/html5/workers/#dedicated-workers-and-the-dedicatedworkerglobalscope-interface

 [4]
 http://www.whatwg.org/specs/web-apps/current-work/multipage/web-messaging.html#web-messaging

 [5]
 http://www.whatwg.org/specs/web-apps/current-work/multipage/web-messaging.html#posting-messages

 [6] PREVIOUS SPECIFICATION STATE!!!
 http://www.w3.org/TR/2011/WD-workers-20110208/#dedicated-workers-and-the-dedicatedworkerglobalscope-interface






Re: postMessage is the new wtf

2011-12-13 Thread Dmitry Lomov
On Tue, Dec 13, 2011 at 12:30 PM, Charles Pritchard ch...@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})


In what we ship today in WebKit, this will be an exception, because cloning
of message ports is not supported.



 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.


 -Charles




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

2011-06-03 Thread Dmitry Lomov
On Thu, Jun 2, 2011 at 10:17 PM, Jonas Sicking jo...@sicking.cc wrote:

 On Thu, Jun 2, 2011 at 4:41 PM, David Levin le...@chromium.org wrote:
 
 
  On Thu, Jun 2, 2011 at 4:24 PM, Jonas Sicking jo...@sicking.cc wrote:
 
  On Thu, Jun 2, 2011 at 2:01 PM, David Levin le...@chromium.org wrote:
  
  
   On Thu, Jun 2, 2011 at 1:27 PM, Glenn Maynard gl...@zewt.org wrote:
   port.postMessage({frameBuffer: frame}, {transfer: [frame], ports:
   [port]});
 
  There are two properties of this approach that I like:
 
  1. It means that objects which you'd like to transfer ownership are
  not second class citizens and can live as part of the normal object
  graph that is posted, together with metadata that goes with it (or
  even as metadata for other things).
 
  2. The receiving side doesn't need to worry about the difference, all
  it gets is the graph of objects that was sent to it.
 
  Yep, I totally agree with this. All of the current solutions being
 discussed
  satisfy both of these in fact.
 
 
   It also raises questions when I see it. When I list an object there
 does
   it
   imply that all children are also transfered or do I have to list each
 of
   them explicitly as well?)
 
  None of the objects which allow transferring of ownership has children
  so this doesn't appear to be a problem at this time. If it indeed does
  turn into a problem, it would seem like a problem no matter what
  solution is used, no?
 
  Not if all objects are transferred.

 Define all objects. Consider something like:

 a = { x: myArrayBuffer1, y: myArrayBuffer2 };
 worker.postMessage(a, { transfer: true });

 In this case the 'a' object is obviously not transferred. Or are you
 proposing that it'd be transferred too somehow?

   Then I wonder what is the use case for this complexity.
   Why not something simpler like this?
   port.postMessage({frameBuffer: frame}, {transfer: true, ports:
   [port]});
   where you can just say indicate that you want the message transfered.
 
  This means that you have to choose between transferring all arrays and
  transferring none of them.
 
  Yep, why add the complication of picking individual items to transfer
  over?  (I'm wary of second system syndrome, which I've seen happen many
  times in various designs.)
 
 
  It also makes it much less explicit which
  objects ends up being mutated.
 
  It is all of them.

 Sure, but what all includes might not be obvious to the web
 developer in all cases. For example if you're receiving an object from
 some subsystem that you intend to do processing on. You later decide
 to do the processing in a thread and throw that object into an array
 alongside with some other data. Some of the other data you are
 throwing in includes some big arrays that you want to avoid copying
 and so you choose to use the transfer rather than copy mode.

 Now you all of a sudden start modifying the data that you got from the
 other subsystem. This is data that you might normally not be even
 looking at. The fact that it happened to contain some ArrayBuffers was
 just a side effect of that that was the data structures that the other
 subsystem uses and was easy for it to return to you.

  Here's a simple use case, suppose I create an array of arrays (a 2d
 array)
  which contains ArrayBuffers.Now I want to transfer this as fast as
 possible
  using postMessage.
  What does my code look like for each of these apis?

 Your proposal:
 w.postMessage(my2darray, {transfer: true});
 vs.
 w.postMessage(my2darray, Array.concat.apply(Array, my2darray));


Hmm, if my2darray is large, the latter is pretty wasteful.



 Now show me the code needed to send a message which contains one big
 buffer from you that you want to transfer, along with some data that
 you got from some other piece of code and which you do not want to
 modify and which may or may not contain ArrayBuffers.


I think this can be reversed: what if you got some data from some other
piece of code that you do not really control and you want to transfer (i.e.
transfer all the ArrayBuffers that are inside that data)?

As in, the library gives you two methods, compute() that returns data and
present(data) that presents it, and you want to pass data from worker to
main thread without really caring what is inside that data.


 / Jonas


Thanks!
Dmitry


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

2011-06-03 Thread Dmitry Lomov
On Thu, Jun 2, 2011 at 11:44 PM, Dmitry Lomov dslo...@chromium.org wrote:



 On Thu, Jun 2, 2011 at 10:17 PM, Jonas Sicking jo...@sicking.cc wrote:

 On Thu, Jun 2, 2011 at 4:41 PM, David Levin le...@chromium.org wrote:
 
 
  On Thu, Jun 2, 2011 at 4:24 PM, Jonas Sicking jo...@sicking.cc wrote:
 
  On Thu, Jun 2, 2011 at 2:01 PM, David Levin le...@chromium.org
 wrote:
  
  
   On Thu, Jun 2, 2011 at 1:27 PM, Glenn Maynard gl...@zewt.org
 wrote:
   port.postMessage({frameBuffer: frame}, {transfer: [frame], ports:
   [port]});
 
  There are two properties of this approach that I like:
 
  1. It means that objects which you'd like to transfer ownership are
  not second class citizens and can live as part of the normal object
  graph that is posted, together with metadata that goes with it (or
  even as metadata for other things).
 
  2. The receiving side doesn't need to worry about the difference, all
  it gets is the graph of objects that was sent to it.
 
  Yep, I totally agree with this. All of the current solutions being
 discussed
  satisfy both of these in fact.
 
 
   It also raises questions when I see it. When I list an object there
 does
   it
   imply that all children are also transfered or do I have to list each
 of
   them explicitly as well?)
 
  None of the objects which allow transferring of ownership has children
  so this doesn't appear to be a problem at this time. If it indeed does
  turn into a problem, it would seem like a problem no matter what
  solution is used, no?
 
  Not if all objects are transferred.

 Define all objects. Consider something like:

 a = { x: myArrayBuffer1, y: myArrayBuffer2 };
 worker.postMessage(a, { transfer: true });

 In this case the 'a' object is obviously not transferred. Or are you
 proposing that it'd be transferred too somehow?

   Then I wonder what is the use case for this complexity.
   Why not something simpler like this?
   port.postMessage({frameBuffer: frame}, {transfer: true, ports:
   [port]});
   where you can just say indicate that you want the message transfered.
 
  This means that you have to choose between transferring all arrays and
  transferring none of them.
 
  Yep, why add the complication of picking individual items to transfer
  over?  (I'm wary of second system syndrome, which I've seen happen many
  times in various designs.)
 
 
  It also makes it much less explicit which
  objects ends up being mutated.
 
  It is all of them.

 Sure, but what all includes might not be obvious to the web
 developer in all cases. For example if you're receiving an object from
 some subsystem that you intend to do processing on. You later decide
 to do the processing in a thread and throw that object into an array
 alongside with some other data. Some of the other data you are
 throwing in includes some big arrays that you want to avoid copying
 and so you choose to use the transfer rather than copy mode.

 Now you all of a sudden start modifying the data that you got from the
 other subsystem. This is data that you might normally not be even
 looking at. The fact that it happened to contain some ArrayBuffers was
 just a side effect of that that was the data structures that the other
 subsystem uses and was easy for it to return to you.

  Here's a simple use case, suppose I create an array of arrays (a 2d
 array)
  which contains ArrayBuffers.Now I want to transfer this as fast as
 possible
  using postMessage.
  What does my code look like for each of these apis?

 Your proposal:
 w.postMessage(my2darray, {transfer: true});
 vs.
 w.postMessage(my2darray, Array.concat.apply(Array, my2darray));


 Hmm, if my2darray is large, the latter is pretty wasteful.



 Now show me the code needed to send a message which contains one big
 buffer from you that you want to transfer, along with some data that
 you got from some other piece of code and which you do not want to
 modify and which may or may not contain ArrayBuffers.


 I think this can be reversed: what if you got some data from some other
 piece of code that you do not really control and you want to transfer (i.e.
 transfer all the ArrayBuffers that are inside that data)?

 As in, the library gives you two methods, compute() that returns data and
 present(data) that presents it, and you want to pass data from worker to
 main thread without really caring what is inside that data.


 / Jonas


So, to clarify, we have two competing requirements here:
1) exercise fine-grained control over which parts of the message are
transfrerred
2) be able to transfer objects opaquely, for modularity or performance
reasons.

Here are two proposals that satisfy both:

a) *Recursive transfer lists*. Allow arbitrary objects, not only
ArrayBuffers, to appear in transfer lists.  ArrayBuffers that are under
objects in transfer lists are transferred, others are cloned. (This leaves
the question, what happens to objects that are shared between objects in
transfer lists and others. It looks like the sane answer

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

2011-06-03 Thread Dmitry Lomov
On Fri, Jun 3, 2011 at 2:15 PM, Andrew Wilson atwil...@google.com wrote:



 On Fri, Jun 3, 2011 at 1:02 PM, Jonas Sicking jo...@sicking.cc wrote:

 On Fri, Jun 3, 2011 at 11:37 AM, Kenneth Russell k...@google.com wrote:
  On Fri, Jun 3, 2011 at 9:46 AM, Glenn Maynard gl...@zewt.org wrote:
  On Fri, Jun 3, 2011 at 11:12 AM, Dmitry Lomov dslo...@google.com
 wrote:
  a) Recursive transfer lists. Allow arbitrary objects, not only
 ArrayBuffers,
  to appear in transfer lists.  ArrayBuffers that are under objects in
  transfer lists are transferred, others are cloned.
 
  This again causes the same forwards-compatibility problem.  If you do
 this:
 
  frame = { video: canvasPixelArrayInstance, histogram: arrayBuffer } }
  postMessage({ frame: frame }, { transfer: frame });
 
  and you expect only histogram to be transferred (since that's all that
  supports it when you write this code), your code breaks when
  CanvasPixelArray later supports it.


Right, but you should not write { transfer : frame }, you should write:
postMessage( { frame: frame }, { transfer: frame.histogram })

in this case. The guidance for transferring objects should be: do not
transfer objects you intend to use on this thread (on main thread, worker)
- only transfer parts that you do not intend to use. This version of
postMessage gives a high-fidelity tool for you to do so if desired, but
handles the opaque case as well.


 
  b) Transfer lists + separate transferMessage method. We still equip
  postMessage with transfer lists, these transfer lists list
 ArrayBuffers, and
  we provide a separate method transferMessage with recursive transfer
  semantics.
  What do people think?
 
  Same problem.
 
  If you want a quicker way to transfer all messages of given types, see
  my previous mail: { transfer: ArrayBuffer }.


(sorry I somehow missed your previous mail when replying)
I do not think filtering by types solve much.

Consider again a case of two library functions compute() returning some data
and present(data) rendering some data, where library user treats the data as
a black box. In first version, library author used ArrayBuffers as part of
data internally, because it is the only data type that is transferrable.
Now, CanvasPixelArray became transferrable as well, and library author
changes the library to compute those as part of the data, to offload more of
the computation to compute phase. With filtering by types, all library
user will need to modify their code as well, to add CanvasPixelArray to a
list of transferrable types in their postMessages.

Again, I think having a transfer list (as some argument to postMessage) is
great solution for high-fidelity control. Low-fidelity, opaque, don't show
me the implementation use cases is what is missing.


 
  Agreed on these points. Using an object graph for the transfer list
  (which is what the recursive transfer list idea boils down to) also
  sounds overly complicated.


It feels that but not solving this as part of messaging spec we just offload
the complexity to the users.


 
  May I suggest to reconsider adding another optional array argument to
  postMessage for the transfer list, rather than using an object with
  special properties?
 
  Points in favor of adding another optional array argument:
 
  1. Less typing, and less possibility that a typo will cause incorrect
 behavior:
   worker.postMessage(objectGraph, null, [ arrayBuffer1ToTransfer,
  arrayBuffer2ToTransfer ]);
 vs.
   worker.postMessage(objectGraph, { transfer: [
  arrayBuffer1ToTransfer, arrayBuffer2ToTransfer] });
 
  2. Possibility of using Web IDL to specify the type of the optional
  array argument (i.e., Transferable[]?). Would be harder to do using
  an object -- requiring either specifying another interface type with
  the ports and transfer attributes, or using any plus
  ECMAScript-specific text.
 
  Points in favor of using an object:
 
  1. Could potentially overload the meaning of the optional ports array
  argument, avoiding adding another argument to postMessage.
 
  2. More extensible in the future.
 
  Thoughts?

 My first thought is that so far no implementer has stepped up and said
 that changing the meaning of the 'ports' argument would not be
 acceptable. Would be great if someone who is reading this thread and
 who works at Google/Apple/Opera could check with the relevant people
 to see if such a change would be possible.


 It's certainly possible - there's nothing intrinsically difficult with
 making this change from an implementor's point of view (I've had my fingers
 in both the WebKit and Chromium MessagePort implementations so I'm
 relatively confident that this would not be prohibitively hard).

 Is it desirable? My knee-jerk reaction is that we should stick with changes
 that are compatible with the existing API (like Ian's original suggestion,
 or adding a separate optional array of transferable objects) - I have no
 data on the number of sites that are using the current API but I