[whatwg] reply() extension to postMessage()

Jonas Sicking jonas at sicking.cc
Sat Mar 1 01:56:43 PST 2008

Ian Hickson wrote:
> On Thu, 14 Feb 2008, Anne van Kesteren wrote:
>> Given that everyone is now updating their postMessage() code anyway, I 
>> wonder if it's possible to quickly make another minor tweak. The 
>> proposal is to remove the source attribute from MessageEvent and replace 
>> it with a reply() method. The semantics of the reply() are probably best 
>> described in terms of equivalence. That is,
>>   e.reply(message)
>> is equivalent to
>>   e.source.postMessage(message, e.origin)
>> except that the latter won't work anymore when reply() is added.
> You might still need the source in order to navigate it, depending on what 
> you're doing. (You can always get a hold of the relevant Window object if 
> it can send you messages, since access to Windows is symmetric.)
> In general I think a better way to do this would be to use a pipe concept, 
> as Dimitri suggests lower down.
> On Thu, 14 Feb 2008, Aaron Boodman wrote:
>> If we're going to add reply, I would like to easily be able to get 
>> replies to a specific message. So extend postMessage to accept a 
>> callback, and then either have reply() call this callback. Like this:
> This could get really confusing from a GC perspective if a script starts 
> keeping track of all its Event objects, since they then each have to keep 
> a function alive on the other side, and Events in browsers probably 
> aren't set up to do that today. It also seems somewhat odd that this sets 
> up an asymmetric relationship.
> On Thu, 14 Feb 2008, Henry Mason wrote:
>> Ooo, I like that idea. I have one concern, however. Presumably, the 
>> message event that is sent as a reply could itself be replied. Since 
>> postMessage's spec currently says:
>> "The postMessage() method must only return once the event dispatch has 
>> been completely processed by the target document (i.e. all three of the 
>> capture, target, and bubble phases have been done, and event listeners 
>> have been executed as appropriate)."
>> ...this behavior could cause some somewhat nasty infinite recursion. So 
>> what if we made reply() asynchronous so that the the reply message event 
>> doesn't need to be dispatched on the original message posting document 
>> until after the original postMessage from the sender is finished 
>> processing?
> This problem exists today with postMessage() too. Do people think we 
> should go fully asynchronous?
> On Thu, 14 Feb 2008, Anne van Kesteren wrote:
>> You really want reply() to have that callback too (for longer 
>> conversations) and at that point it starts getting icky.
> Indeed.
>> I came up with another idea to address the issue you mention. We let 
>> postMessage() return a UUID and give MessageEvent an "id" attribute. 
>> When postMessage() is invoked a UUID is generated and returned. This 
>> same UUID is set on the event that is dispatched. When reply is invoked 
>> on that event object it creates an event that again has the same UUID. 
>> Both parties can have multiple conversations that way by checking the 
>> UUID of the message.
> I don't thikn we want to be doing ID checking. That's icky too. :-)
> On Thu, 14 Feb 2008, Aaron Boodman wrote:
>> I'm trying to get away from checking IDs because the common case I have 
>> seen is either one-way (tell the widget to do something), or two-way 
>> (ask the widget for some piece of information). Having to match up IDs 
>> is a pain for a simple question/answer.
>> Perhaps there could be a conversation object or something. Maybe that's 
>> getting too weird though...
> No, I think that's the direction to go in.
> On Thu, 14 Feb 2008, Dimitri Glazkov wrote:
>> Speaking of a conversation object: I've been using a Pipe abstraction 
>> with Gears workers to some degree of success. I am wondering if/how 
>> something like this could exist at a spec level.
> Over the past few days I've been working on something similar:
>    http://hixie.ch/specs/dom/messages/0.9

So this draft makes one of the two endpoints cross scope, i.e. it is 
created in one window, and are then passed over to the other. This is a 
major pain security wise. For example, what happens to expando 
properties set on the object? Currently only window and location objects 
cross scopes as useful objects and there have been several security 
issues with this due to being hard to implement.

I would instead suggest having an api such as:

window A:
myPipe = createMessagePipe();
myPipe.onmessage = function(e) { alert("A got this:" + e.message) }
otherWindow.postMessage("here ya go", myPipe);

window B:
window.onmessage = function (e) {
   pipeFromOtherGuy = e.pipe;
   pipeFromOtherGuy.onmessage = function () { alert("ack from B") }
   setTimeout(sendMoreStuff, 10);

sendMoreStuff() {
   pipeFromOtherGuy.postMessage("more stuff");

The messages are synchronous so this would alert, in order:
A got this:thanks!
ack from B
A got this:more stuff
ack from B

This also generally seems simpler. If you try to pass a pipe to 
postMessage that has aleady has been passed in an earlier postMessage 
call an exception is thrown.

I too am strongly in favor of having synchronous message. Asynchronous 
things are in general harder for developers to understand. And while 
Synchronous things generally are evil when it comes to network loads, I 
see no such problems here.

/ Jonas

More information about the whatwg mailing list