Must built-in prototypes also be valid instances? (Was: Why DataView.prototype object's [[Class]] is "Object"?)

Mark S. Miller erights at google.com
Tue Oct 2 10:47:58 PDT 2012


Having isFoo succeed on an instance of Bar is correct. But there's another
case that's more worrisome:

Foo foo = new Foo();
Baz baz = Object.create(foo);

By Allen's pattern, isFoo will also succeed on an instance of baz. OTOH,
were the branding done with a WeakMap or the brandcheck done with an own
check....



On Tue, Oct 2, 2012 at 10:12 AM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote:

>
> On Oct 1, 2012, at 10:37 PM, Brendan Eich wrote:
>
> > Brendan Eich wrote:
> >> But if we have a solid branding mechanism (like Domado's ideal in
> latest browsers? ;-) then that should be used universally and this becomes
> a don't-care.
> >
> > Just to be crystal clear:
> >
> > * in pre-ES6 browsers, no @@toStringTag in the language to hack around
> with.
> >
> > * in ES6+ browsers, the better branding mechanism and @toStringTag (one
> @) as public symbol, no worries.
> >
> > Yes, this makes a fork in JS code that wants to do tag testing. Old code
> must use O_p_toString_call (original value of, safe call binding) and
> string compare. New code wants the better and universal scheme.
> >
> > /be
> >
>
> Yes, exactly what I envision.  New code that needs to do branding should
> do it in a new way.  But I still think we need to protect the integrity of
> the old mechanism in the presence of @@toStringTag.
>
> It is also probably worthwhile taking a look at how internal branding is
> done in the draft spec. for Map.
>
> We also need to be careful about making a branding mechanism too
> prominent.  If we do, too many people will misuse it as a poor man's
> nominal type system when they really should be doing behavior typing (or
> even more likely no explicit type checking at all).  Past experience is
> that excessive class brand checking is an anti-pattern for dynamic OO
> languages.
>
> I think we have all the language features need to do reliable branding by
> ES programmers where they need it.  We just need to establish the patterns
> for doing that. Here is the one I propose:
>
> private @FooBrand;
> class Foo {
>    constructor() {
>         /* establish the internal Fooness of the instance */
>         this. at FooBrand = true;
>    }
> }
> Foo.isFoo = function (obj) {return !!obj. at FooBrand};
>
>
> private @BarBrand;
> class Bar extends Foo {
>    constructor() {
>         super();
>         /* establish the internal Barness of the instance */
>         this. at BarBrand = true;
>    }
> }
> Bar.isBar = function (obj) {return !!obj. at BarBrand};
>
> Note that an instance of Bar will be true for both Foo.isFoo and Bar.isBar
>
> This  pattern is fine as long as it is ok that anything processed by the
> Foo or Bar constructor gets branded because not, anybody can do:
>    let myFoo = Foo.call({ });
>
> If you really need to strongly tie instantiation with branding you
> probably have to use a factory function:
>
> module Fooishness {
>    export function FooFactory ( ){return  new Foo};
>    FooFactory.isFoo = function (obj) {return !!obj. at FooBrand};
>
>    private @FooBrand;
>    class Foo {
>       constructor() {
>            /* establish the internal Fooness of the instance */
>            this. at FooBrand = true;
>       }
>    }
> }
>
> Allen
>
>
>
>
>


-- 
    Cheers,
    --MarkM
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20121002/83a197a9/attachment.html>


More information about the es-discuss mailing list