2

Steps:

  1. run code in the Firefox
  2. wait 5 seconds (important!)
  3. Press OK or Cancel
  4. expect flag == 0, but it is 10.

var flag;

function myFunction(){
    flag = 0 
    console.info("initial", flag);
    setTimeout(function(){
        flag = 10;
    }, 200);
  
    confirm("conf");
   
    alert("should be 0: "+flag);
}

document.getElementById('button').onclick=myFunction;
   
                          
<button type="button" id="button">Click Me!</button>
vitalh
  • 404
  • 1
  • 7
  • 12
  • I waited for 30 seconds, but still it shows 0. Don't tell me now, it should be 5 seconds only. :P – rajuGT Nov 16 '15 at 17:30
  • I think the question is, why does the timeout fire *before the "click" event loop is complete*. – Pointy Nov 16 '15 at 17:32

3 Answers3

5

Because unlike many browsers, Firefox may allow the JavaScript thread to run other code while the alert, prompt, and confirm modals are showing, suspending the current code. (See end of answer for more on about the "may" in that sentence.) The task where the alert etc. was called is suspended, so the code in that task doesn't proceed, but other tasks are allowed to run.

This means

  • Timers can get their callback

  • Ajax completion handlers can run

  • Etc.

There's never JavaScript running concurrently in two places, but Firefox does let the thread run other tasks while a task is suspended by those modals.

It's an Firefox quirk. I first learned about it right here on Stack Overflow, thanks to bobince.


Why I said "may" allow the JavaScript thread to run: It used to be fairly reliable (olders versions of Firefox). I had no trouble replicating it on Firefox 29 or 38. Firefox 42 seems to make it much less likely, but it does still happen.

I would expect (though I could be wrong) that Mozilla will change this to be in line with other browsers, as one could argue it violates JavaScript's run-to-completion semantics for tasks, and those semantics just got beefed up and clarified by the latest specification.

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
1

I tried this in both Firefox and in Chrome. In Firefox I got 10 for a result. In Chrome I got 0 for a result. Likely Firefox and Chrome have different concurrency models when it comes to the confirm function. Firefox is likely running the modal dialog in a separate thread, allowing the setTimeout to continue to run in its own thread (and incrementing the value of flag after 200 milliseconds). Chrome is likely running the modal dialog in the same thread as setTimeout, thus blocking the running of the setTimeout (and not allowing the value of flag to be incremented).

Bradley Holt
  • 618
  • 5
  • 7
0

What? You set flag to 10. Why would you expect it to be 0?

Michael Lorton
  • 43,060
  • 26
  • 103
  • 144
  • How does the timer event happen while the "click" event loop is still active? – Pointy Nov 16 '15 at 17:32
  • 1
    *"Why would you expect it to be 0?"* Because on Chrome, IE, and I think Safari, it's `0`. `confirm` is one of the built-in stop-the-world modals. Except on Firefox. – T.J. Crowder Nov 16 '15 at 17:35