<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Wed, Apr 29, 2015 at 1:06 AM, Brendan Eich <span dir="ltr"><<a href="mailto:brendan@mozilla.org" target="_blank">brendan@mozilla.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Kevin Smith wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
So what would the ideal Promise.resolve semantics do?  I'm not sure, maybe use SpeciesConstructor instead of [[PromiseConstructor]]?<br>
</blockquote>
<br>
This removes the wart in my view, has no less integrity. C. Scott?</blockquote><div><br></div><div>Making this concrete, here would be the new text for 25.4.4.5 Promise.resolve(x):</div><div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">The resolve function returns either a new promise resolved with the passed argument, or the argument itself if the argument is a promise produced by this constructor.<br>1. Let C be the this value.<br>2. If IsPromise(x) is true,<br>    a. Let constructor be the value of SpeciesConstructor(x, %Promise%)</blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">    b. If SameValue(constructor, C) is true, return x.<br>3. If Type(C) is not Object, throw a TypeError exception.<br>4. Let S be Get(C, @@species).<br>5. ReturnIfAbrupt(S).<br>6. If S is neither undefined nor null, let C be S.<br>7. Let promiseCapability be NewPromiseCapability(C) </blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">[...remainer elided...]</blockquote><div> </div></div><div>Step 2a is the only change.  (It was previously "Let constructor be the value of x's [[PromiseConstructor]] internal slot.")</div><div><br></div><div>Thinking this through, the purpose of the `@@species` property, from the spec: "Promise prototype methods normally use their this object’s constructor to create a derived object. However, a subclass constructor may over-ride that default behaviour by redefining its @@species property."</div><div><br></div><div>So with this change, `P.resolve()` is guaranteed to return an object whose constructor property is `P.@@species`, whether it takes the shortcut in step 2 or not.  That seems pleasantly less warty.</div><div><br></div><div>The alternative (implemented in core-js) is:<br></div><div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">2. If IsPromise(x) is true,<br>    a. Let proto be the value of x.[[Prototype]]</blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">    b. If SameValue(proto, GetPrototypeFromConstructor(C, "%PromisePrototype%")) is true, return x.<br></blockquote></div><div><br></div><div>But that seems to break the expected behavior of @@species.  That is, a promise subclass `P1` with `P1.@@species == P2` would shortcut objects of type `P1` through `P1.resolve()` but return objects of type `P2` if the shortcut wasn't taken.  (Forgive the looseness of the word "type" here.)</div><div><br></div><div>That seems somewhat surprising.  But I don't have a concrete use case in mind for setting `Promise[@@species]`.  Perhaps someone else has one, and can say what behavior they'd prefer to see?</div><div><br></div><div>Lacking such a justification, the first alternative (using [[SpeciesConstructor]]) seems to be more consistent with the rest of the spec and less surprising.  So that has my vote.</div><div>  --scott</div><div><br></div></div></div></div>