YuzuJS/setImmediate

Execution order for setImmediate via postMessage is wrong:

Yaffle opened this issue · 5 comments

my test, Firefox browser:

asyncTest("Execution order for setImmediate via postMessage", 1, function () {
    var orderOfExecution = '';
    var tmp = setImmediate(function () {

    });
    clearImmediate(tmp);

    window.onmessage = function (event) {
      event = event || window.event;
      if (event.data === 'some other message') {
        orderOfExecution += '1';
        if (orderOfExecution.length === 2) {
          strictEqual(orderOfExecution === '12', true, "Execution order is wrong");
          start();
        }
      }
    };
    window.postMessage('some other message', '*');

    setImmediate(function () {
      orderOfExecution += '2';
      if (orderOfExecution.length === 2) {
        strictEqual(orderOfExecution === '12', true, "Execution order is wrong");
        start();
      }
    });

});

You really need to be more clear as to why this is a failure of the implementation according to the spec.

Am I correct that if you do window.postMessage, then setImmediate, you are expecting the window.postMessage callback to happen before the setImmediate callback? Can you point to any spec that specifies this?

Furthermore, what is the point of the setImmediate/clearImmediate(tmp) at the top of the function? Without it, does the test still "fail"?

You are right, seems, according to spec, even this code:

var s = '';
window.onmessage = function (event) {
  s+= event.data;
};
for(var i = 0; i < 10; i++) {
  window.postMessage(i, '*');
}

setTimeout(function () {
  alert(s);
}, 0);

can alert different results and in Safari and Chrome postMessage actually async and doen't respect calling order .... so my test with

postMessage and setImmediate is bad

and i found another issue with execution order in Google Chrome (i have Chrome 14) :

asyncTest("Execution order test", 1, function () {
   var j = 0;
   setImmediate(function () {
     j = 1;
   });
   setTimeout(function () {
     strictEqual(!!j, true, "Execution order is wrong");
     start();
   }, 0);
});

this test works fine in all browsers, except Chrome 14,
in Chrome it fails sometimes and sometimes not...

The reason for that last failure is Chrome has been moving away from the HTML5 spec, which mandates that setTimeout have a minimum of 4ms (i.e. setTimeout(..., 0) should be the same as setTimeout(..., 4)). So, they are making setTimeout(..., 0) behave much like setImmediate, and I guess sometimes a Chrome-setTimeout(..., 0) gets executed even sooner than a setImmediate.

So, basically, it's Chrome's fault, and sadly there's nothing we can do about it.