domenic/promises-unwrapping

Potential inconsistency in using [[PromiseConstructor]] in Promise Resolution Handler

domenic opened this issue · 6 comments

See https://bugs.ecmascript.org/show_bug.cgi?id=2513 by @cscott. I need to think about this more.

Can we use @@defer and tell implementers informally to use [[PromiseConstructor]] until they implement Symbols?

I think I would prefer to use .constructor but I need to dig back through those algorithms to see why I used [[PromiseConstructor]] in the first place.

The simplifications from the last TC39 meeting might also totally change that section of the internals anyway.

FWIW I'd like to actually implement some subclasses and get some experience here before I make recommendations one way or another.

Three interesting promise subclasses:

  1. TimeoutPromise -- reject after a timeout. Trivial to implement, but it might be worth thinking about what operations are going to "inherit" the timeout behavior via then, where the timeouts start, etc.

  2. BindPromise -- bluebird has a notion of "promises which bind this". I think this is possible to implement using promise subclasses, although you'd use a different subclass for every this value. Again, it would be nice if the behavior of this subclass ended up matching bluebird's.

  3. MonadicPromise -- lots of noise on es6-discuss about chain/then. It might be possible to create a Promise subclass which enforced a single level of unwrapping by boxing/unboxing its value appropriately. Tracing the flow of MonadicPromise through Promise.then would be very interesting.

It would also be worth thinking hard about the behavior of the combinators Promise.all and Promise.race in the presence of such subclasses.

Maybe I'll learn nothing from this exercise --- I'll have to try it and see!

Oh, and the renaming of Promise.cast to Promise.resolve potentially affects this, too. If you have, for example, a TimeoutPromise, the new Promise.resolve() won't create a new timer (which is good). Similarly, the new Promise.resolve(MonadicPromise) is not going to create a new wrapper (which is bad?). I can probably work around this the same way as for BindPromise (that is, every MonadicPromise will have a unique constructor) but then I have to pay careful attention to all the uses of Promise.resolve (nee Promise.cast) in the spec).

I also discovered a minor issue with the check in step 8 of CreatePromiseCapabilityRecord (http://people.mozilla.org/~jorendorff/es6-draft.html#sec-createpromisecapabilityrecord) -- it makes it harder to create "new constructor every time" methods like MonadicPromise and BindPromise. See https://mail.mozilla.org/pipermail/es-discuss/2014-February/036293.html (and https://gist.github.com/cscott/b1966d485807d9a8cc39).