I was under the impression that then handler functions are processed in the order they are added.
For example, if you run this code:
function getResolvedPromise(result) {
  return new Promise((resolve, reject) => {
    console.log(`Promise executor, result will be ${result}`);
    resolve(result);
  });
}
function logThen(label, result) {
  console.log(`[${label}] Promise then, result = ${result}`);
  return result;
}
// Shows that then handlers get run in the order they are added.
const prom1 = getResolvedPromise("prom1");
const prom2 = getResolvedPromise("prom2");
prom2.then(logThen.bind(null, "1"));
prom2.then(logThen.bind(null, "2"));
prom2.then(logThen.bind(null, "3"));
prom1.then(logThen.bind(null, "4"));
prom1.then(logThen.bind(null, "5"));
prom1.then(logThen.bind(null, "6"));
Then this is what gets logged. This makes sense to me.
Promise executor, result will be prom1
Promise executor, result will be prom2
[1] Promise then, result = prom2
[2] Promise then, result = prom2
[3] Promise then, result = prom2
[4] Promise then, result = prom1
[5] Promise then, result = prom1
[6] Promise then, result = prom1
However, if you run this:
// Order of execution is interleaved when then handlers are directly attached?
const prom1 = getResolvedPromise("prom1")
  .then(logThen.bind(null, "1"))
  .then(logThen.bind(null, "2"))
  .then(logThen.bind(null, "3"));
const prom2 = getResolvedPromise("prom2")
  .then(logThen.bind(null, "4"))
  .then(logThen.bind(null, "5"))
  .then(logThen.bind(null, "6"));
Then this is what gets logged.
Promise executor, result will be prom1
Promise executor, result will be prom2
[1] Promise then, result = prom1
[4] Promise then, result = prom2
[2] Promise then, result = prom1
[5] Promise then, result = prom2
[3] Promise then, result = prom1
[6] Promise then, result = prom2
What explains this interleaving behavior?
Note that the specification contains some relevant information here. Specifically, it says this about HostEnqueuePromiseJob:
Jobs must run in the same order as the HostEnqueuePromiseJob invocations that scheduled them.
And if we look at the specification for Promise.prototype.then, we see that it calls HostEnqueuePromiseJob. So the only way this makes sense to me is that the then calls are being called in an interleaved order. But... I don't really get how this happens, since the two code samples I posted seem equivalent to me.
