On Thu, Aug 22, 2013 at 9:13 AM, Tab Atkins Jr. <[email protected]>wrote:
> On Thu, Aug 22, 2013 at 8:04 AM, Mark S. Miller <[email protected]> > wrote: > > You're right, my code is wrong. What I meant is: > > > > Object.create(p, {Promise: {value: Promise}}).Promise(....) > > > > In other words, the Promise constructor might get supplied as its "this" > an > > object that passes "p instanceof Promise" for innocent reasons other that > > "new" or .call. The question is, what does the Promise constructor test > in > > order to determine whether it should use its coercion behavior or > > constructor behavior. If the test were "p instanceof Promise", then the > > above call, which was clearly intending to invoke its coercion behavior, > > would accidentally invoke its constructor behavior instead. > > Okay, that's still defending a user from themselves, but whatever, I'm > fine with that. > > > In any case, postponing subclassing till ES6 when we have the needed > > support, I think I know how to "solve" the problem. It is a bit weird. > > > > var Promise = (function(){ > > "use strict"; // of course > > > > var brand = new WeakMap(); > > > > // only ever called with "new" > > function HiddenPromiseConstructor(callback) { > > // initialize "this", which it can assume starts fresh and > > trustworthily uninitialized > > brand.set(this, true); > > } > > > > function Promise(arg) { > > if (Object.getPrototypeOf(this) === Promise.prototype && > > !(brand.has(this))) { > > // assume likely called with "new", but do not trust > "this" > > return new HiddenPromiseConstructor(arg) > > } else { > > // assume called for coercion behavior. Ignore this > > if (brand.has(arg)) { > > return arg; > > } else { > > return Promise.of(arg); > > } > > } > > } > > HiddenPromiseConstructor.prototype = Promise.prototype; > > > > // initialize Promise.prototype > > // initialize Promise statics > > return Promise > > })(); > > There's an even easier method. Using "new" doesn't do anything > magical, it just sets `this` to be a fresh object with the right > proto. We can do that ourselves, and you can return whatever object > you want from the constructor, so you can avoid the > HiddenPromiseConstructor by just using an Object.create() call: > > var self = Object.create(Promise.prototype); > > Put that at the top of your constructor code, and return it at the > end, rather than `this`. Yes, this is equivalent to the HiddenPromiseConstructor approach. > Use whatever method you feel like for > determining that you were called as a constructor. > What test to use for this determination was the entire question! > > Otherwise, yeah, your code is how to do it, until we get the ability > to specifically respond to being called vs being constructed. > Ok, I think we have our ES5 polyfill. > > ~TJ > -- Cheers, --MarkM
_______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

