Killing `Promise.fulfill`

Mark S. Miller erights at google.com
Thu Aug 22 09:24:15 PDT 2013


On Thu, Aug 22, 2013 at 9:13 AM, Tab Atkins Jr. <jackalmage at gmail.com>wrote:

> On Thu, Aug 22, 2013 at 8:04 AM, Mark S. Miller <erights at google.com>
> 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130822/2d3a97de/attachment.html>


More information about the es-discuss mailing list