Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

code executed in wrong order in Firefox with setTimeout after alert

Run the following code in any browser( try it several times):

console.log('processing: task #1');
setTimeout(function(){
  console.log('processing: task #3');
},0);
alert('See console logs');
console.log('processing: task #2');

In my understanding, the above code would result console output being:

"processing: task #1"
"processing: task #2"
"processing: task #3"

But in Firefox( v38.0.1), it produces the following output:

"processing: task #1"
"processing: task #3"
"processing: task #2"

Please explain why Firefox do it this way. Don't know if it's a bug or Firefox's own standard.

You can see a live demo here: http://jsbin.com/cijonu

like image 532
Greg Avatar asked May 29 '15 07:05

Greg


1 Answers

This is a bug. The HTML5 specification doesn't allow event handlers to fire while an alert is being shown:

Section 6.1.4 defines the event loop.

In 6.1.4.2 this section also helps provide some guarantees about the order in which events are fired (point 1 of the event loop algorithm) and that the document gets rendered after an event handler returns (point 4.3)

Section 6.4 defines the timer initialisation steps for setTimeout:

... 14. Queue the task task.

point 12 of this section also provides a guarantee about the relative ordering of multiple timeouts - a timeout issued later may not fire before a timeout issued earlier unless it has a shorter timeout

Section 6.5 defines the alert behavior.

  1. Optionally, abort these steps. (For example, the user agent might give the user the option to ignore all alerts, and would thus abort at this step whenever the method was invoked.)

  2. Show the given message to the user.

  3. Optionally, pause while waiting for the user to acknowledge the message.

(note: pausing is mandatory for confirm and prompt as they return based on the user actions)

The specification of pausing says:

Some of the algorithms in this specification, for historical reasons, require the user agent to pause while running a task until a condition goal is met. This means running the following steps:
...
3. Wait until the condition goal is met. While a user agent has a paused task, the corresponding event loop must not run further tasks, and any script in the currently running task must block. User agents should remain responsive to user input while paused, however, albeit in a reduced capacity since the event loop will not be doing anything.

(emphasis mine)

Note that if alert does not pause, the console logs must still be in order: First synchronous execution completes (log #2), then the timeout fires (log #3), then the user closes the alert. As observed by the page javascript, the behavior is the same as if the user has closed the alert box immediately.

like image 95
John Dvorak Avatar answered Oct 07 '22 01:10

John Dvorak