Eric Seidel wrote:
1.  JS content authors will want an async API.

Sometimes, for the large applications; small apps won't care.  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]  Further, nothing says browser implementations must or will 
continue to enforce hard limits on recursion.

function messageHandler(messageEvent) {
// We assume calling into our complex functions might run out of stack space, so we just handle this in a timeout:
setTimeout(0, function() { realMessageHandler(messageEvent) } );
}

function realMessageHandler(messageEvent) {
 // handle the message...
 // and, reply to the message
 messageEvent.source.postMessage("response message");
}

Furthermore, note that the above behavior is actually *insecure* if the handler 
authenticates the sender and discloses some secret in his response, because 
|messageEvent.source| may have been navigated to a different origin.  Making 
the API async basically requires the optional origin argument always be 
provided to postMessage, adding API complexity.  If a piece of information 
doesn't have to be [present] for the system to [usually] work, sooner or later 
it won't be [and the system won't work].[1]


I forsee JS authors implementing their own asynchronous behavior, as shown above.

I do, too, in some cases; I just don't think it's worth sacrificing simplicity 
or security in the common case for the special, rare case.


2.  JS engine implementors will want an async API.

I would rather we didn't prevent FireFox or Safari

"Firefox", the second "f" isn't capitalized.  :-)

(Only possible for frames which are not of the same origin.   Same-origin
frames already assume they can grab at each others innards in a synchronous manner.) postMessage imposes a NEW requirement that all connected frames to be run from the same thread (or somehow synchronize the threads after the first postMessage() call is made).

Wrong; if a window can get a reference to another window, same-origin or not, 
run-to-completion already requires synchronous behavior.  If some piece of JS 
is in flight, every client-side change it can detect *must* be one it has 
caused.

This requirement would seem even worse for Microsoft, since IE8 looks like it's multi-process. A synchronous postMessage would require IE8 to keep all frames which have references to each other in the same process.

postMessage imposes no new requirement for the appearance of synchrony, no 
matter how the implementation chooses to achieve it.


Asynchrony was brought up in a separate thread ("[whatwg] reply() extension to 
postMessage()") two months ago, before the source-navigation discussion made this 
secret-exposure danger more easily noticeable.  I made basically the same arguments then 
as I make now; I also noted that sync can replicate async (again ignoring the uncommon 
case of being right at the recursion limit), whereas the reverse is not true:

I think I favor sync postMessage over async because async capabilities are a strict subset of sync capabilities. You can always use setTimeout with the sync model to get async behavior; if the model is async you can't replicate sync behavior.

Note also that nothing prevents an implementation with a recursion limit from 
requiring that postMessage always guarantee enough available frames to dispatch 
the setTimeout continuation, although nobody I know has actually done this.


In sum, I think worrying about recursion limits is the wrong thing to do, sync 
behavior is more flexible, and we shouldn't sacrifice security for the uncommon 
recursion-limit case.

Jeff

0.  Python, thy name is AWESOME.  <http://www.python.org/dev/peps/pep-0020/>
1.  Astonishingly PEP 20 doesn't have any dicta related to security, but 
<http://www.wiretip.com/?about> comes to the rescue, with a few tweaks.

Reply via email to