joyent/node — pull request #8325 by vkurchatkin (2014-09-06 16:35:44+00:00)
Title: node: support v8 microtask queue

Since v8 introduced `Promise` support it became possible to schedule tick callback which will be executed only after next javascript invocation:

```javascript
Promise.resolve().then(function () {
process.nextTick(function () {
console.log('tick');
});
});

setTimeout(function () {
console.log('timeout');
}, 2000);
```

It may look like this issue affects only first tick, but it's not:

```javascript
setTimeout(function () {
process.nextTick(function () {
Promise.resolve().then(function () {
process.nextTick(function () {
console.log('tick');
});
});

setTimeout(function () {
console.log('timeout');
}, 2000);
});
}, 0);
```

This happens because v8 uses microtask queue to run promise callbacks (and also `Object.observe` callbacks), which is essentially the same as nextTick queue. Together they don't play really nice: nextTick callback may schedule a microtask and vice versa. If queues are flushed in any particular order some callbacks won't be called. To handle this problem we need to flush queues in a loop until both are empty.

This PR implements the following algorithm:

1. Execute all callbacks, that are CURRENTLY present in nextTick queue (not the ones added recursively)
2. Flush microtask queue
3. Check if there are more callbacks in nextTick queue, if so, go to 1.

This attempts to make two microtasks queues behave as one. Unfortunately, microtask queue has higher priority and can potentially prevent nextTick callbacks added before from running:

```javascript
setTimeout(function () {
Promise.resolve().then(function () {
process.nextTick(function () {
console.log('never printed');
});

function block () {
Promise.resolve().then(block);
}

block();
});
}, 0)
```

It looks like there is nothing we can do about it without direct control over microtask queue. For same reason there is no way to make microtask queue work with domains.

fixes #7714

/cc @tjfontaine @trevnorris @indutny