resolve()/reject() on Promise subclasses and @@species
Domenic Denicola
d at domenic.me
Thu Nov 5 02:36:51 UTC 2015
I still think everything should go through @@species. I don't understand the utility of @@species if it is not uniformly applied to constructing new instances (in both instance and static methods). But it seems that ES15 decided to only use @@species for instance methods so I guess that's where we're stuck.
From: "C. Scott Ananian" <ecmascript at cscott.net>
Sent: Nov 5, 2015 3:20 AM
To: Allen Wirfs-Brock
Cc: es-discuss
Subject: Re: resolve()/reject() on Promise subclasses and @@species
As referenced in the cited thread
(https://esdiscuss.org/topic/performpromiseall#content-6) there are
actually two uses of the Promise constructor in the definition of
`all` and `race`. To quote myself:
> [N]ote that the implementations given for `Promise.all` and `Promise.race` use Promises in two different ways: (1) every element of the array argument has `C1.resolve(elem).then(....)` applied to it, and (2) the result is constructed with `NewPromiseCapability(C2)`. It's not entirely clear to me that C1 and C2 should be the same. Consider the `TimeoutPromise`: do we want to apply a timeout to every element individually *and* to the result as a whole?
>
> It seems that C1 might use species (to avoid the timeout/weak reference), but C2 ignore it (to apply the timeout/weak reference to the final result)
>
>[...] [I]f we decided that `WeakPromise.all()` should return a `WeakPromise` then I'd suggest that we change step 6 from:
>> Let promiseCapability be NewPromiseCapability(C).
>to
>> Let promiseCapability be NewPromiseCapability(this).
>in both `Promise.all` and `Promise.race`, but leave the definition of C otherwise alone, so that internally-created promises honor the species.
The subtly of this detail of the spec was (for me at least) one of the
reasons I didn't push for a change to `Promise.all` and `Promise.race`
at the time. And, as I wrote then, the current semantics do have a
plausible consistency, given future `Promise.prototype.all` and
`Promise.prototype.race` methods.
I'm certainly willing to reopen this for discussion, but I'd like to
see some hard thought given to the two separate uses in the
definition.
--scott
On Fri, Oct 30, 2015 at 5:21 PM, Allen Wirfs-Brock
<allen at wirfs-brock.com> wrote:
> +1
>
> Allen
>
> On Oct 30, 2015, at 10:19 AM, Claude Pache <claude.pache at gmail.com> wrote:
>
>
> Le 29 oct. 2015 à 03:51, Boris Zbarsky <bzbarsky at MIT.EDU> a écrit :
>
> I was just implementing subclassing of Promise in Gecko, when I realized
> that given a Promise subclass MyPromise these two calls:
>
> MyPromise.race([])
> MyPromise.all([])
>
> will take MyPromise[@@species] into account when creating the return value,
> but these two calls:
>
> MyPromise.resolve()
> MyPromise.reject()
>
> will not; they will invoke MyPromise itself, not MyPromise[@@species].
>
> This is because
> http://www.ecma-international.org/ecma-262/6.0/#sec-promise.all and
> http://www.ecma-international.org/ecma-262/6.0/#sec-promise.race do the
> whole @@species thing but
> http://www.ecma-international.org/ecma-262/6.0/#sec-promise.reject and
> http://www.ecma-international.org/ecma-262/6.0/#sec-promise.resolve do not.
>
> Is this behavior intentional? If so, I'd really like to understand the
> reason for it.
>
> -Boris
>
>
> Relevant discussion: https://esdiscuss.org/topic/performpromiseall
>
> As I understand, the specified behaviour is an accident of history.
> Previously, `Promise.resolve()` and `Promise.reject()` used the species
> pattern in order to determine the constructor to be used, just as
> `Promise.all()` and `Promise.race()`. Then, at the last minute, it was
> decided that it wasn’t the best semantics for `Promise.resolve()`, and it
> was corrected. For `Promise.all()` and `Promise.race()`, the motivation
> wasn’t stronger than the lack of time.
>
> Should it be corrected before @@species is widely implemented? I think so.
> The arguments I give are:
>
> * Overall consistency in the language. Except for the two offending Promise
> static methods, all uses of `@@species` in the ES2015 spec (15 uses) are for
> the following pattern: Starting from one instance, one constructs a derived
> object for that instance. (The effective lookup of the @@species property is
> factored in the SpiecesConstructor and ArraySpeciesCreate abstract
> operations.)
>
> * Also, in static methods like `Promise.all` and `Promise.race`, a
> constructor is explicitly provided by the user: simply use it. Compare with
> what is done for arrays:
>
> Array.from(someArray) // use the Array constructor explicitly provided.
> Array.of(x, y, z) // ditto
>
> someArray.slice(0) // compute the constructor to be used through some
> algorithm involving @@species.
> [].concat(x, y, z) // ditto
>
> —Claude
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151105/61a733d4/attachment-0001.html>
More information about the es-discuss
mailing list