I'm reading this article from V8 about how ES2017 introduced an optimization for async/await to reduce the number of Promises needed in runtime execution. Essentially avoiding an extra Promise when the value being awaited is already a Promise. This also enabled efficient async stack trace to be collected in Errors.
In the article it gave a high-level explanation of how async function translate into internal operations. And here is a figure they used in question:
I think the author is using ECMAScript terms for naming the internal operations.
createPromise
-> Promise ConstructorperformPromiseThen
-> PerformPromiseThenresolvePromise
-> Promise Resolve Functions
What I don't understand though is the throwaway
promise. It's passed to the performPromiseThen
operation. However the signature for PerformPromiseThen
is:
PerformPromiseThen( promise, onFulfilled, onRejected [ , resultCapability ] )
The last optional argument being a PromiseCapability Record. I also can't quite grasp the idea of this PromiseCapability Record. It seems to be used in async iterators but not really sure how. It doesn't seem to be the same thing throwaway
promise was representing. So my question is what exactly is this throwaway
promise, and what is the semantics of this parameter passed to performPromiseThen
?
I can rewrite their internal operations back into plain Promise based on my understanding, but the throwaway
promise is still a missing piece that I cannot have a mental mapping to things I can understand.
function foo(v) { // resumable function foo(v) {
const implicit_promise = new Promise // implicit_promise = createPromise();
((resolvePromise, _throw) => {
// // 1. wrap v in a promise
const promise = new Promise(resolvePromise => // promise = createPromise();
resolvePromise(/* promise, */ v)); // resolvePromise(promise, v);
// // 2. attach handlers for resuming foo
/* throwaway = createPromise(); */ // throwaway = createPromise();
promise.then( // performPromiseThen(promise,
res => resume(/* «foo», */ res), // res => resume(«foo», res),
err => _throw(/* «foo», */ err), // err => throw(«foo», err),
/* throwaway */); // throwaway);
function resume(/* «foo», */ res) { // // 3.a suspend foo ...
w = /* resumed */ res; // w = suspend(«foo», ...);
resolvePromise(/* implicit_promise, */ w); // resolvePromise(implicit_promise, w);
}
}); // // 3.b ... and return implicit_promise
return implicit_promise; // suspend(..., implicit_promise);
}