setTimeout uses the same message queuing system as XHR, DOM events, or communicating with stuff that has its own stack like iframes or workers. That's why a function with a timeout of 0 will not fire until after it's enclosing function has popped. Functions block. Waiting for messages doesn't. That's the model for JS concurrency.