Promise finally

Raul-Sebastian Mihăilă raul.mihaila at gmail.com
Sat Feb 24 09:18:27 UTC 2018


If TC39 finds a better solution than the existing one in good time, I don't
think it makes sense for it to wait for another year to implement it while
having a broken `Promise.prototype.finally` in the browsers.

I've been thinking about a solution and, if my solution is correct, the
changes are very small. In essence, in this solution,
`Promise.prototype.finally` behaves very similar to
`Promise.prototype.then`. The resolve functions associated with a promise
capability, if they are obtain using CreateResolvingFunctions, they will
have an internal [[FinallySourcePromise]] slot which will be used to
resolve the promise created by `Pormise.prototype.finally`. The rest of the
changes consist basically of passing around the value of this slot. This
solution is much more intuitive in terms of what `finally` is expected to
do, which also has the good property of not incurring 2 extra ticks (not
even 1 extra tick).

CreateResolvingFunctions(promise, finallySourcePromise)
  update step 3: Let resolve be CreateBuiltinFunction(stepsResolve, «
[[Promise]], [[AlreadyResolved]], [[FinallySourcePromise]] »).
  insert new step 6: Set resolve.[[FinallySourcePromise]] to
finallySourcePromise.

GetCapabilitiesExecutor Functions
  A GetCapabilitiesExecutor function is an anonymous built-in function that
has a [[Capability]] and a [[FinallySourcePromise]] internal slots.

NewPromiseCapability(C, finallySourcePromise = undefined)
  update step 5: Let executor be CreateBuiltinFunction(steps, «
[[Capability]], [[FinallySourcePromise]] »).
  insert new step 7: Set executor.[[FinallySourcePromise]] to
finallySourcePromise.

Promise ( executor )
  insert step 8: Let finallySourcePromise be undefined.
  insert setp 9: If executor has a internal slot [[FinallySourcePromise]]
    Let finallySourcePromise be executor.[[FinallySourcePromise]]
  update step 8 (which now becomes step 10): Let resolvingFunctions be
CreateResolvingFunctions(promise, finallySourcePromise).

PromiseResolveThenableJob(promiseToResolve, thenable, then,
finallySourcePromise)
The job PromiseResolveThenableJob with parameters promiseToResolve,
thenable, then and finallySourcePromise performs the following steps:
  update step 1: Let resolvingFunctions be
CreateResolvingFunctions(promiseToResolve, finallySourcePromise).

Promise.prototype.finally(onFinally)
  Let promise be the this value.
  If IsPromise(promise) is false, throw a TypeError exception.
  Let C be ? SpeciesConstructor(promise, %Promise%).
  Let resultCapability be ? NewPromiseCapability(C, promise).
  Return PerformPromiseThen(promise, onFinally, onFinally,
resultCapability).

Promise Resolve Functions
  update step 7: If Type(resolution) is not Object, then
    Let finallySourcePromise be F.[[FinallySourcePromise]]
    If finallySourcePromise is undefined
      return FulfillPromise(promise, resolution).
    Else
      If finallySourcePromise.[[PromiseState]] is "rejected"
        return RejectPromise(promise,
finallySourcePromise.[[PromiseResult]])
      Else
        return FulfillPromise(promise,
finallySourcePromise.[[PromiseResult]])
  update step 12: Perform EnqueueJob("PromiseJobs",
PromiseResolveThenableJob, « promise, resolution, thenAction,
F.[[FinallySourcePromise]] »).
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20180224/15794500/attachment-0001.html>


More information about the es-discuss mailing list