(Apologies if the threading on this gets messed up. I was not subscribed to the list when the original message was sent.)<br><br>I want to paint Eric's scenario more strongly, because it seems like people think if it would rarely blow up then it doesn't matter.<br>
<br>If you want to handle _any_ request sent by a synchronous postMessage, and you aren't a cowboy programmer, you _must_ either call no functions, or use a setTimeout() continuation. You CANNOT know how deep your caller's stack is, so you CANNOT safely do anything that could add to the stack depth. It doesn't matter if the stack will not _commonly_ be too deep, or if it isn't too deep for the callers that you know about right now -- it might be too deep at some point (after someone else changes the caller code, for example), and your sync handler will blow up. And the very sorts of things you'd want postMessage for are frequently cases where others will write mashups and use your code in ways you hadn't planned. For this reason, I think talking about "the common case" misses the point -- a sync API is completely useless to anyone trying to write _any_ serious code defensively, large app or small, because it cannot be made safe except by using setTimeout to make it async, at which point synchronicity has bought you nothing. On the contrary, it has added great risk, because any coder who fails to understand the threat posed here and fails to transform all postMessage handlers into async ones risks his code blowing up. I prefer not to have APIs that force you to take action if you don't want to shoot yourself in the head.<br>
<br>If you're still not convinced that coders would care, remember that stack depths vary by interpreter, too. I believe in pocket IE you have a ridiculously small stack depth [12?]. On this kind of platform, the recursion limits get hit in the common case rather than the uncommon, even in today's code without postMessage(). While other mobile devices may be a little more forgiving, smaller recursion limits are always going to be more likely on embedded devices, and embedded devices are just going to get more popular.<br>
<br>And as Eric mentioned, even on desktop browsers, apps of any reasonable size (like gmail) already jump through hoops TODAY to avoid getting near any stack limits. This isn't some vague theoretical concern. It's very real and already impacts web apps. So if we're trying to write APIs to enable even more powerful, more robust web applications, sync postMessage completely fails to accomplish that.<br>
<br>Below I have some less important replies to various points in Jeff's post.<br><br>Jeff Walden wrote:<br><blockquote style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;" class="gmail_quote">
Eric Seidel wrote:<br>> 1. JS content authors will want an async API.<br><br>Sometimes, for the large applications; small apps won't care.</blockquote><div><br>Besides the comments I wrote above that amount to "all the time, for all large apps, and most small ones too, you will want async for safety":<br>
<br>I admit to spending more time in the C++ space than the JS space, but it seems like in most cases where you'd actually want to call postMessage, you don't really know how long the target may take to act on your request, and you don't necessarily want to block. The async use case seems more common to me.<br>
<br>(Incidentally, I also find the name bizarre. If it's a sync API, why not "callFunction" or at the very least "sendMessage", which [in Windows land] doesn't imply asynchronicity the way "postMessage" does [in both the Windows and common-english-usage senses of "post"].)<br>
</div><br><blockquote style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;" class="gmail_quote">As you note, the workaround of immediately packaging up a setTimeout continuation isn't difficult. I tend to think worrying about the N-1 case is designing a bit too much for the special cases, personally. Special cases aren't special enough to break the rules.[0]</blockquote>
<div><br>Again, ignoring my "this isn't a special case" comments:<br><br>Given the number of websites relying on this feature right now (0?), how do you know what the special cases are? I'm skeptical that async usage is so exceptional as you seem to think. Besides my own intuition above, the JS developers at Google I've spoken to have all been surprised postMessage is currently specified to be synchronous -- they were all expecting async.<br>
</div><br>setTimeout may not be terribly difficult, but if it's the common case, it also forces the JS engine to jump through hoops that it doesn't need to for no benefit, forces programmers to contort their app in ways that don't express their intent as well, and is less obvious to someone newly approaching the API.<br>
<br><blockquote style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;" class="gmail_quote">Further, nothing says browser implementations must or will continue to enforce hard limits on recursion.<br>
</blockquote><br>Nothing says they won't, either. And when the status quo is that they do, I will believe this restriction will disappear when I see it.<br><br>Even if, say, SpiderMonkey stops enforcing a recursion limit, so what? If I want my app to actually run everywhere, I need to assume the limit is present until _every_ UA gets rid of it. Surely you agree the chances of that happening are small. See my comments at top about mobile devices, where these limits make lots of sense.<br>
<br><blockquote style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;" class="gmail_quote">Making the API async basically requires the optional origin argument always be provided to postMessage, adding API complexity.<br>
</blockquote><br>I don't really see how making an optional argument be a non-optional argument would result in a more complex API. It doesn't raise the maximum number of arguments to provide, and it reduces the number of forms the function takes by one. Furthermore, if a recipient needs to handle the message asynchronously via setTimeout, they'll need this anyway. Forcing callers to provide it is a security win at that point, not a loss.<br>
<br>Or, if you like, take the position that the argument should stay optional, and if someone for some reason doesn't have to care about security (?!), they can avoid passing it. Although I'm not sure this is a particularly great idea :)<br>
<font style="font-family: arial,sans-serif;" size="2"><br></font><blockquote style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;" class="gmail_quote"><font style="font-family: arial,sans-serif;" size="2">If some piece of JS is in flight, every client-side change it can detect *must* be one it has caused.</font></blockquote>
<div><br>Are you sure? I'm reading the docs in section 4.1.4, and it seems to say that this is only true for changes within the unit of related browsing contexts. If it is possible to get a reference to a Window outside this group, then your statement is untrue. But I'm not sure whether that's possible.<br>
<br>PK<br></div>