<div dir="ltr">I have not responded on list yet because I haven't yet been able to find the time to absorb this thread. But since Allen mentioned it, what I wrote was:<div><br></div><div><br></div><div><div class="gmail_extra" style="font-size:12.8000001907349px">The invariant I am interested in:</div><div class="gmail_extra" style="font-size:12.8000001907349px"><br></div><div class="gmail_extra" style="font-size:12.8000001907349px"><br></div><div class="gmail_extra" style="font-size:12.8000001907349px">In a realm where we (the trusted defender who runs first) make Promise defensive as follows</div><div class="gmail_extra" style="font-size:12.8000001907349px"><br></div><div class="gmail_extra" style="font-size:12.8000001907349px">* Freeze everything primordial, as SES does</div><div class="gmail_extra" style="font-size:12.8000001907349px"><br></div><div class="gmail_extra" style="font-size:12.8000001907349px">* Make a DefensivePromise subclass of Promise that differs minimally, hopefully only by ensuring that its instances are frozen.</div><div class="gmail_extra" style="font-size:12.8000001907349px"><br></div><div class="gmail_extra" style="font-size:12.8000001907349px">* "Promise = DefensivePromise;" do "Promise" below refers to DefensivePromise</div><div class="gmail_extra" style="font-size:12.8000001907349px"><br></div><div class="gmail_extra" style="font-size:12.8000001907349px">* Freezing whitelisted global properties, as SES currently does for ES5 globals, but for ES6 including "Promise"</div><div class="gmail_extra" style="font-size:12.8000001907349px"><br></div><div class="gmail_extra" style="font-size:12.8000001907349px"><br></div><div class="gmail_extra" style="font-size:12.8000001907349px">then it must be the case that</div><div class="gmail_extra" style="font-size:12.8000001907349px"><br></div><div class="gmail_extra" style="font-size:12.8000001907349px">    Promise.resolve(anything).then(anycallback)</div><div class="gmail_extra" style="font-size:12.8000001907349px"><br></div><div class="gmail_extra" style="font-size:12.8000001907349px">for an anything provided by a potential attacker, when executed in the middle of a turn does not call callback during that turn. If it calls anycallback at all, it calls it back *as* a later turn, i.e., in a later turn starting from an empty stack.</div></div><div><br></div><div><br></div><div><br></div><div><br><div><br></div><div><br></div><div><br></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Apr 29, 2015 at 9:49 AM, Allen Wirfs-Brock <span dir="ltr"><<a href="mailto:allen@wirfs-brock.com" target="_blank">allen@wirfs-brock.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><span class=""><br><div><div>On Apr 29, 2015, at 8:44 AM, C. Scott Ananian wrote:</div><br><blockquote type="cite"><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></div></div></blockquote><br></div></span><div>But SpeciesConstructor (or any access to x's @@species) goes through `x.constructor` and my recollection is that the motivation for adding [[PromiseConstructor]] was that 'constructor'  was not sufficiently tamper proof.  From that perspective, it seems that SpeciesConstructor is actually worse than just accessing `x.constructor`.</div><div><br></div><div>Also, in a private message Mark Miller mentioned that the primarily  security invariant he's concerned about really relates to the behavior of the `then` method of the object returned by `Promise.resolve(x)`.  Neither testing `construct` or SpeciesConstructor really tells you anything about `then`.   It seems that the root problem here is trying to apply nominal type based reasoning to JS.</div><span class="HOEnZb"><font color="#888888"><div><br></div><div>Allen</div><br></font></span></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature">    Cheers,<br>    --MarkM</div>
</div>