<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Wed, Apr 29, 2015 at 1:00 PM, Mark S. Miller <span dir="ltr"><<a href="mailto:erights@google.com" target="_blank">erights@google.com</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"><div dir="ltr"><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">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></blockquote><div><br></div><div>How about:</div><div>```</div><div>var goodPromises = new WeakSet();</div><div>class DefensivePromise {</div><div>  constructor(x) {</div><div>    super(x);</div><div>    Object.freeze(x);<br></div><div>    // check this.constructor here if you are paranoid.</div><div>    goodPromises.add(this);</div><div>  }</div><div>  resolve(x) {</div><div>    if (goodPromises.has(x)) {</div><div>      return super.resolve(x);</div><div>    }</div><div>    return new DefensivePromise(function(r){r(x);});</div><div>  }</div><div>}</div><div>```</div><div>Doesn't seem like this needs special support in the Promise spec.</div><div><br></div><div>Note that the `goodPromises` set won't be fooled by passing in `DefensivePromise` as `new.target` to `Promise` without actually running the `DefensivePromise` constructor.</div><div>  --scott<br></div></div></div></div>