W3C home > Mailing lists > Public > whatwg@whatwg.org > March 2010

[whatwg] using postMessage() to send to a newly-created window

From: Ian Hickson <ian@hixie.ch>
Date: Thu, 25 Mar 2010 08:31:04 +0000 (UTC)
Message-ID: <Pine.LNX.4.64.1003250105560.29348@ps20323.dreamhostps.com>
On Mon, 21 Dec 2009, Dirk Pranke wrote:
> 
> In the course of testing something today, I attempted to create a window 
> and immediately post a message to it, and was surprised that it didn't 
> seem to work.
> 
> E.g.:
> 
> var w = window.open("http://x");
> w.postMessage("hello, world", "*");
> 
> w never got the message - this seemed to be consistent across Safari,
> Chrome, and FF (all I had installed on my Mac at the time, so
> apologies to Opera, IE, and anyone else I've left out).

It got the message, it just got it when the window's document was 
about:blank and before the scripts in that window were ready to receive 
any messages.


> Is this supposed to work? If not, is there a reliable way for the the 
> source to know when it is safe to send a message to the target?

If it's same-origin, the simplest solution is to wait for onload.

If it's cross-origin, there is by design no mechanism to expose when the 
page is ready short of the other site announcing it (by sending a message 
to its opener, in this case).


> If this isn't supposed to work, can we state this explicitly in the 
> spec?

Where would you like it mentioned and what would you like it to say?


On Tue, 5 Jan 2010, Jonas Sicking wrote:
> 
> This is a sort of suboptimal state of affairs though. Compare to 
> workers, which also do not load synchronously, but which you can 
> immediately send messages to using postMessage().
> 
> We could use a similar solution for windows postMessage as we use for 
> worker postMessage.

I assume you mean provide a mechanism by which messages are queued until 
the page does something that causes the events to be fired?

We could, but it wouldn't actually help in this particular case (since the 
first message is sent to the about:blank document, and I presume we would 
nuke all pending messages upon navigation).

It seems relatively easy to work around the problem in the case of 
windows (just send a message when you're ready), so I'm not sure it's 
worth it.


On Tue, 5 Jan 2010, Adam Barth wrote:
> 
> The existing content would be racy because postMessage returns to the 
> main event loop before dispatching.  It would at least make the content 
> more predictable.  :)

Only content that tries to communicate to a document while it's loading. 
How common is that likely to be? In the usual case, scripts only run after 
onload, and the iframes delay onload.

The risk is that anyone using addEventListener() would never get the 
message.


On Tue, 5 Jan 2010, Dirk Pranke wrote:
>
> I understand the rationale, and the workaround you suggest does work, (I 
> have tested it, in FF, Safari and Chrome). But, as Jonas mentioned, this 
> isn't what we do with workers, and it feels counter-intuitive to me (I'm 
> having trouble thinking of other async messaging models that require an 
> application-level handshake like this before messaging can commence). 
> Are there reasons other than implementation complexity (an okay reason) 
> or backwards-compatibility (a better reason) not to have the post work 
> in this case? Put differently, would anything break (other than a rather 
> oddly written app that explicitly counted on this behavior) if this did 
> work?

If we changed it, it would be multiple years before IE changed to match. 
Is it worth having IE be non-compliant for that long, rather than having 
interoperability for that long, given that this is basically an edge case 
and quite managable?


> As an alternative, would it be possible to create an onChildLoad() event 
> in the parent so that the parent could reliably send a message without 
> needing the child's cooperation? These seems only marginally better than 
> having the child post to the parent, so it may not be worth it ...

For iframes, onload does that. For same-origin content, onload on the 
target does that. For cross-origin cross-window content, not exposing this 
is by design.


On Tue, 5 Jan 2010, Darin Fisher wrote:
>
> It sounds tempting to say that the postMessage should be queued until 
> the newly opened window is loaded, but what point in time is that 
> exactly?  Is that after the load event is dispatched on the newly opened 
> window?
> 
> Note: a newly opened window can begin communicating with its opener much 
> earlier (via inline script execution).
> 
> However, if we try to dispatch the postMessage events before the load 
> event then the newly opened window may not have registered its event 
> handlers yet. (A future <script> tag may define the event handler.)  
> So, I think we would have to delay until the load event for the 
> semantics to be sane.

Indeed, I wouldn't be a fan of waiting for a load event before sending the 
events.


> There is perhaps a more critical issue that we should consider.  What
> happens if the named window already exists?
> 
> Consider this case:
> 
> window.open("http://a/", "foo");
> ...
> var w = window.open("http://b/", "foo");
> w.postMessage("bar", "*");
> 
> I suspect the postMessage would be dispatched in this case, but the 
> event dispatch would probably go to the document at http://a/ instead of 
> http://b/.

That's why you're not supposed to use "*". This problem always exists -- 
your target window could get renavigated in between your navigating it and 
the task that sends the event being queued.


On Wed, 6 Jan 2010, Michael A. Puls II wrote:
> On Tue, 05 Jan 2010 23:29:40 -0500, Dirk Pranke <dpranke at chromium.org> 
> wrote:
> 
> > As an alternative, would it be possible to create an onChildLoad() 
> > event in the parent so that the parent could reliably send a message 
> > without needing the child's cooperation? These seems only marginally 
> > better than having the child post to the parent, so it may not be 
> > worth it ...
> 
> In Firefox, you can do stuff like this:
> 
> var w = window.open("handler.html");
> w.addEventListener("DOMContentLoaded", function(e) {
>    var targetWin = e.target.defaultView.
>    targetWin.postMessage("Hello", "domain");
> }, false);
> 
> But, I think that only works in Firefox. In Opera at least, I'm sure it 
> doesn't work.

I believe the spec unambiguously defines what should happen in that case, 
now that everything is defined in terms of the event loop.

-- 
Ian Hickson               U+1047E                )\._.,--....,'``.    fL
http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'
Received on Thursday, 25 March 2010 01:31:04 UTC

This archive was generated by hypermail 2.4.0 : Wednesday, 22 January 2020 16:59:22 UTC