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

2012-10-03 Thread Mark S. Miller
On Tue, Oct 2, 2012 at 9:05 PM, Norbert Lindenberg 
ecmascr...@norbertlindenberg.com wrote:

 TC 39, I need decisions so that I can finish the Internationalization spec
 and send it to the Ecma GA:

 1) Instances of Intl.Collator, Intl.NumberFormat, and Intl.DateTimeFormat
 currently have [[Class]] Object. Should this change to Collator,
 NumberFormat, and DateTimeFormat, respectively?

 2) If the answer to 1) is yes: The prototype objects of Intl.Collator,
 Intl.NumberFormat, and Intl.DateTimeFormat currently have [[Class]]
 Object. Should this change to Collator, NumberFormat, and
 DateTimeFormat, respectively?

 3) If the answer to 1) or 2) is no: The prototype objects of
 Intl.Collator, Intl.NumberFormat, and Intl.DateTimeFormat currently have
 all the state that allows them to be used as instances. Should they not
 have that state, and instead be plain objects with methods?

 If I don't get votes from at least 10 of the usual TC 39 attendees within
 the next 24 hours, and a clear majority for change, the spec will remain as
 approved at the meeting two weeks ago.


#1 no
#2 no
#3 yes. They should be plain objects with methods but no instance state.
This makes them better resemble classes.



 Thanks,
 Norbert


 On Sep 29, 2012, at 23:08 , Brendan Eich wrote:

  Norbert Lindenberg wrote:
  Last week TC 39 approved a standard defining three new built-in
 constructors whose instances and prototype objects all have [[Class]]
 Object. Also, the prototype objects are not constructed by their
 respective constructors, but initialized by them, e.g., as
 Intl.Collator.call({}).
 
  Are you suggesting they should have Collator, NumberFormat, and
 DateTimeFormat, respectively, and the prototypes be specified as being
 constructed by their constructors?
 
  All else equal, yes (sorry for not flagging these).
 
  Any non-equal elses in sight?
 
  /be




-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-03 Thread Mark S. Miller
On Tue, Oct 2, 2012 at 10:13 AM, Brendan Eich bren...@mozilla.com wrote:

 Allen Wirfs-Brock wrote:

 On Oct 1, 2012, at 9:56 PM, Brendan Eich wrote:

  Allen Wirfs-Brock wrote:

 We can try to tell ES implementors that they must do certain things in
 order to be in conformance but that really doesn't work for code written by
 users of the language.

 You're right, we'd be letting usercode, not just some (benign or malign,
 but if malign then game over already) host object, spoof a core language
 built-in.

 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.

 /be


 Great, but this is really an orthogonal issue from my extensible
 Obj.proto.toString design.


 I know, but I'm trying to simplify the spec further than you are.

 (Allen and I had a phone call -- thanks to that, better understanding of
 what's at stake.)

 Unfortunately, toString is used as a brand test by old code and SES
 (targeting pre-ES6 browsers). But rather than enshrine this forever, I
 would like to discuss breaking one case slightly in order to have a simpler
 spec.

 The case that the draft spec upholds is

 * New ES6+ browser, old and new script mixing, old script uses
 O_p_toString_call to tag-test and new script uses @toStringTag to spoof.

 I'd like to break this case, allowing old script in a new browser to be
 spoofed by new script using @toStringTag.

 Mark, is this a worry? If so then perhaps we are stuck with the
 complicated Object.prototype.toString in the latest draft.


It is a worry, but my position remains that I am willing to take this
chance iff ES6 has an adequate branding mechanism.




 If not, and I would argue any SES subset must protect its old script
 from any spoofing new script, then we should try to unify [[NativeBrand]]
 and @@toStringTag by eliminating use of the former in
 Object.prototype.toString's spec, making the latter the sole extension
 mechanism.


and with a new branding mechanism that a defensive program can feature test
for. In the absence of the feature, it should be valid for a defensive SES
program to assume that ES5 [[Class]] remains a valid brand. We can't have
an interval where the old mechanism is broken and there is no safe
substitute.




 Allen and I also discussed the plan I intend to try in SpiderMonkey:
 making Date.prototype, Number.prototype, etc. test as Object according to
 the O_p_toString_call tag test. We think this should not affect SES or any
 real code (as Oliver postulated).


I agree. And if it does affect SES, we can still fix it. From the SES pov,
this one is easy.




 Comments welcome,

 /be




-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-03 Thread Brendan Eich

Mark S. Miller wrote:


Allen and I also discussed the plan I intend to try in
SpiderMonkey: making Date.prototype, Number.prototype, etc. test
as Object according to the O_p_toString_call tag test. We think
this should not affect SES or any real code (as Oliver postulated).


I agree. And if it does affect SES, we can still fix it. From the SES 
pov, this one is easy.


I filed https://bugzilla.mozilla.org/show_bug.cgi?id=797686 -- will try 
to get a patch up in the next week.


/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-02 Thread David Bruant
2012/10/2 Mark S. Miller erig...@google.com

 On Mon, Oct 1, 2012 at 9:02 PM, Brendan Eich bren...@mozilla.com wrote:



 Words on paper still carry force but they do not necessarily have prompt
 effects, or any effects. It depends on the people reading them and
 implementing, and trying to follow the rules. Those people are much more
 likely to audit their (closed, per release, typically) set of host objects
 and fix any spoofers.


 I think we're agreeing but for one thing. The force of a normative
 specification is that violations can be added to test262, so that they
 stand out like a sore thumb, putting pressure on the violator to fix it. We
 already did this successfully with one host object violation.


But test262 can't really get out of its way and test host objects since
they are implementation-dependent. I actually reported a couple of
erroneous test cases that were relying on DOM features to work.
We need WebIDL tests. For that matter, I'll try to attend testthewebforward
in Paris at the end of the month [1] and start working on that if I do
attend. I estimate the amount of work to get decent WebIDL (ECMAScript
binding of browser APIs) coverage as ridiculously huge.

David

[1] http://testthewebforward.org/paris-2012.html
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-02 Thread Allen Wirfs-Brock

On Oct 1, 2012, at 9:56 PM, Brendan Eich wrote:

 Allen Wirfs-Brock wrote:
 We can try to tell ES implementors that they must do certain things in order 
 to be in conformance but that really doesn't work for code written by users 
 of the language.
 
 You're right, we'd be letting usercode, not just some (benign or malign, but 
 if malign then game over already) host object, spoof a core language built-in.
 
 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.
 
 /be
 

Great, but this is really an orthogonal issue from my extensible 
Obj.proto.toString design.

I did not intent that to be a branding mechanism.  Using toString for branding 
of builtins is a crock that was enabled by the ES spec leaking one of its 
internal abstractions.  toString's real role in life is just as a debugging aid 
that allows any object to present a string rendering of itself.  My primary 
goal with Obj.proto.toString was to make that debugging aid more easily 
extensible as make it easier for developer to define new object abstractions 
(classes) that are reasonable identified in their Obj.proto.toString renderings.

The only place that branding enters into this is in recognizing that existing 
working code uses Obj.proto.toString as a brand test for ES builtins.  The ~ 
spoofing prevention is only there to ensure that such code isn't broken. 

A new branding mechanism may be a fine thing to have (more on that in another 
reply) and if we have one it should be universally applied.  But that doesn't 
really have anything to do with toString as an extensible way to get a string 
object description or with the need to support legacy use of toString as a 
brand check on ES=5.1 builtins.

Allen
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-02 Thread Allen Wirfs-Brock

On Oct 1, 2012, at 4:08 PM, Domenic Denicola wrote:

 On Oct 1, 2012, at 18:58, Brendan Eich bren...@mozilla.org wrote:
 
 I am warming up to the way CoffeeScript does things -- not the translation 
 scheme, __extends, __super__ -- rather, the plain Object instance created as 
 C.prototype that has B.prototype as its [[Prototype]] but has shadowing 
 'constructor' set to C.
 
 If I'm understanding correctly, this would be the same as
 
 C.prototype = Object.create(B.prototype);
 C.prototype.constructor = C;
 
 which I thought was the recommended approach (although by who or where, I 
 admit I can't quite pinpoint). Am I on the right track? And can anyone else 
 comment on the commonality or recommendedness of this pattern, to see if 
 we're paving the right cow paths?
 

This is essentially how ES6 classes get wired up.  Actually what they do is 
closer to:

  
let tempProto = Object.create(B.prototype);
tempProto.constructor = function (constructor params) {constructor body);
tempProto.constructor.__proto__ = B;
tempProto.constructor.prototype = tempProto;
C=tempProto.constructor;



___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-02 Thread Kevin Reid
On Mon, Oct 1, 2012 at 9:56 PM, Brendan Eich bren...@mozilla.com 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.


MarkM suggested I should expound on what Domado does.

Domado uses an abstraction which I called 'Confidence', which I invented in
order to provide class-like behavior in terms of ES5; it is designed to
provide the security properties we needed with a minimum of implementation
mechanism, and is therefore not purely a branding abstraction. It uses one
WeakMap keyed by the instances (the objects confided in); the value is a
plain {} object which stores all of the “private fields” of the key-object.
There are four operations provided by a Confidence:

1. confide: add an instance to the WeakMap and create its private-state
record.

  function TameNode() {
TameNodeConf.confide(this);
  }

2. guard: test that an instance is in the WeakMap and return it or throw.

  var TameNodeT = TameNodeConf.guard;
  ...
  TameBackedNode.prototype.appendChild = nodeMethod(function (child) {
child = TameNodeT.coerce(child);
...
  });

3. p: given an instance, return its private-state record.

  var np = TameNodeConf.p.bind(TameNodeConf);
  ...
  TameBackedNode.prototype.removeChild = nodeMethod(function(child) {
...
np(this).feral.removeChild(np(child).feral);
...
  });

4. protectMethod: given a function, return a function with a guarded this.

  var nodeMethod = TameNodeConf.protectMethod;
  (usage examples above)


Note that unlike closure-based encapsulation, Confidence provides _sibling
amplification_; that is, a node method on one object can access the private
properties of another object, not only its own. This is not ideal as a
default for writing robust programs, but is useful to Domado since its
siblings interact (e.g. appendChild operates on two nodes from the same
DOM). An alternative abstraction which deemphasized sibling amplification
would be, for example, if protectMethod were defined such that the
wrapped function received an extra private-state argument and there was no
separate p operation (though sibling amplification can still be achieved
by having a protected method not exposed on the prototype).

The WeakMap used is the browser's WeakMap if available; otherwise we use an
emulation layer with inferior but sufficient garbage-collection properties
(implemented by SES or ES5/3; Domado is unaware of the distinction).
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-02 Thread Allen Wirfs-Brock

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.@FooBrand = true;
   }
}
Foo.isFoo = function (obj) {return !!obj.@FooBrand};


private @BarBrand;
class Bar extends Foo {
   constructor() {
super();
/* establish the internal Barness of the instance */
this.@BarBrand = true;
   }
}
Bar.isBar = function (obj) {return !!obj.@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.@FooBrand};

   private @FooBrand;
   class Foo {
  constructor() {
   /* establish the internal Fooness of the instance */
   this.@FooBrand = true;
  }
   }
}

Allen




___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-02 Thread Brendan Eich

Allen Wirfs-Brock wrote:

On Oct 1, 2012, at 9:56 PM, Brendan Eich wrote:


Allen Wirfs-Brock wrote:

We can try to tell ES implementors that they must do certain things in order to 
be in conformance but that really doesn't work for code written by users of the 
language.

You're right, we'd be letting usercode, not just some (benign or malign, but if 
malign then game over already) host object, spoof a core language built-in.

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.

/be



Great, but this is really an orthogonal issue from my extensible 
Obj.proto.toString design.


I know, but I'm trying to simplify the spec further than you are.

(Allen and I had a phone call -- thanks to that, better understanding of 
what's at stake.)


Unfortunately, toString is used as a brand test by old code and SES 
(targeting pre-ES6 browsers). But rather than enshrine this forever, I 
would like to discuss breaking one case slightly in order to have a 
simpler spec.


The case that the draft spec upholds is

* New ES6+ browser, old and new script mixing, old script uses 
O_p_toString_call to tag-test and new script uses @toStringTag to spoof.


I'd like to break this case, allowing old script in a new browser to be 
spoofed by new script using @toStringTag.


Mark, is this a worry? If so then perhaps we are stuck with the 
complicated Object.prototype.toString in the latest draft.


If not, and I would argue any SES subset must protect its old script 
from any spoofing new script, then we should try to unify 
[[NativeBrand]] and @@toStringTag by eliminating use of the former in 
Object.prototype.toString's spec, making the latter the sole extension 
mechanism.


Allen and I also discussed the plan I intend to try in SpiderMonkey: 
making Date.prototype, Number.prototype, etc. test as Object according 
to the O_p_toString_call tag test. We think this should not affect SES 
or any real code (as Oliver postulated).


Comments welcome,

/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-02 Thread Kevin Smith
 private @FooBrand;
 class Foo {
constructor() {
 /* establish the internal Fooness of the instance */
 this.@FooBrand = true;
}
 }
 Foo.isFoo = function (obj) {return !!obj.@FooBrand};


Using this strategy, will isFoo not fail, if the specified object came from
a different global context (frame)?

Kevin
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-02 Thread Mark S. Miller
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 al...@wirfs-brock.comwrote:


 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.@FooBrand = true;
}
 }
 Foo.isFoo = function (obj) {return !!obj.@FooBrand};


 private @BarBrand;
 class Bar extends Foo {
constructor() {
 super();
 /* establish the internal Barness of the instance */
 this.@BarBrand = true;
}
 }
 Bar.isBar = function (obj) {return !!obj.@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.@FooBrand};

private @FooBrand;
class Foo {
   constructor() {
/* establish the internal Fooness of the instance */
this.@FooBrand = true;
   }
}
 }

 Allen







-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-02 Thread Herby Vojčík



Allen Wirfs-Brock wrote:

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.@FooBrand = true;
}
}
Foo.isFoo = function (obj) {return !!obj.@FooBrand};


private @BarBrand;
class Bar extends Foo {
constructor() {
 super();
 /* establish the internal Barness of the instance */
 this.@BarBrand = true;
}
}
Bar.isBar = function (obj) {return !!obj.@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.@FooBrand};

private @FooBrand;
class Foo {
   constructor() {
/* establish the internal Fooness of the instance */
this.@FooBrand = true;
   }
}
}


var iWillBeFoo = {};
Fooishness.FooFactory().constructor(iWillBeFoo);

In fact, it has its logic to `newFoo.@FooBrand = true;` in factory, 
which solves it, hopefully cleanly enough.



Allen


Herby
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-02 Thread Allen Wirfs-Brock

On Oct 2, 2012, at 10:18 AM, Kevin Smith wrote:

 
 private @FooBrand;
 class Foo {
constructor() {
 /* establish the internal Fooness of the instance */
 this.@FooBrand = true;
}
 }
 Foo.isFoo = function (obj) {return !!obj.@FooBrand};
 
 Using this strategy, will isFoo not fail, if the specified object came from a 
 different global context (frame)?
 
 Kevin
 

Indeed it would, but why shouldn't it?  Foo in another  frame is a different 
class.  If you need to do cross-frame brand, that seems like an additional 
requirement would require additional mechanism.

Wouldn't a WeakMap branding scheme has similar issues. You would need to share 
via some means a common WeakMap among constructors in different frames.  Just 
like to make symbol based branding work for this requirement you would have to 
share a private symbol between frames.

Allen


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-02 Thread Allen Wirfs-Brock

On Oct 2, 2012, at 10:47 AM, Mark S. Miller wrote:

 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

Yes, you're correct an own property check is needed in isFoo.  That is is one 
disadvantage of use private symbols as brands rather than WeakMaps.  On the 
other hand, if you have many instances that need to be branded I suspect that 
the distributed symbol based technique is going to have a better performance 
profile than the WeakMaps.  My old GC writer self cringes at the possible perf 
impact many WeakMaps with large numbers of entries.

Allen



___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-02 Thread Allen Wirfs-Brock

On Oct 2, 2012, at 10:52 AM, Herby Vojčík wrote:

 
 
 Allen Wirfs-Brock wrote:
 
 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.@FooBrand};
 
private @FooBrand;
class Foo {
   constructor() {
/* establish the internal Fooness of the instance */
this.@FooBrand = true;
   }
}
 }
 
 var iWillBeFoo = {};
 Fooishness.FooFactory().constructor(iWillBeFoo);
 
 In fact, it has its logic to `newFoo.@FooBrand = true;` in factory, which 
 solves it, hopefully cleanly enough.
 
 Allen
 
 Herby
 

Good catch, I forgot that the constructor is still exposed as a property on the 
instance.   The other way to prevent the constructor from being used to brand a 
pre-existing object is force an instantiation inside the constructor:

private @FooBrand;
class Foo {
  constructor() {
   let newFoo = Object.create(Foo.prototype);
   /* establish the internal Fooness of the instance */
   newFoo.@FooBrand = true;
   return newFoo;
  }
}
Foo.isFoo = function (obj) {return Reflect.hasOwn(obj,@FooBrand)  
!!obj.@FooBrand};

But this prevents Foo branding of subclasses of Foo.  There is a tension here 
that I don't think is necessarily resolvable. To me, it is another example why 
such class branding should only be used in specific high integrity situations 
and not as a general practice for all classes.

Allen
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Test for [[Construct]] invocation (was: Re: Must built-in prototypes also be valid instances? (Was: Why DataView.prototype object's [[Class]] is Object?))

2012-10-02 Thread Herby Vojčík



Allen Wirfs-Brock wrote:

On Oct 2, 2012, at 10:52 AM, Herby Vojčík wrote:



Allen Wirfs-Brock wrote:

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.@FooBrand};

private @FooBrand;
class Foo {
   constructor() {
/* establish the internal Fooness of the instance */
this.@FooBrand = true;
   }
}
}

var iWillBeFoo = {};
Fooishness.FooFactory().constructor(iWillBeFoo);

(here I missed `.call`)


In fact, it has its logic to `newFoo.@FooBrand = true;` in factory, which 
solves it, hopefully cleanly enough.


Allen

Herby



Good catch, I forgot that the constructor is still exposed as a property on the 
instance.   The other way to prevent the constructor from being used to brand a 
pre-existing object is force an instantiation inside the constructor:

private @FooBrand;
class Foo {
   constructor() {
let newFoo = Object.create(Foo.prototype);
/* establish the internal Fooness of the instance */
newFoo.@FooBrand = true;
return newFoo;
   }
}
Foo.isFoo = function (obj) {return Reflect.hasOwn(obj,@FooBrand)  
!!obj.@FooBrand};

But this prevents Foo branding of subclasses of Foo. There is a
tension here that I don't think is necessarily resolvable. To me, it
 is another example why such class branding should only be used in
specific high integrity situations and not as a general practice for
all classes.


Well, here (and in other cases, too) it would be handy to be able to 
distinguish whether the call is constructor (new operator, super() call 
in class constructor) or plain call (the rest). It can be 
`arguments.isConstruct`, for example.


Than, it would simply be solved by `if (!arguments.isConstruct) return;` 
(or throw) as the first line in constructor.



Allen


Herby

P.S.: Alternatively, this line can be intrinsic property of class 
constructor, but this makes class special and not a desugaring any more...

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Test for [[Construct]] invocation (was: Re: Must built-in prototypes also be valid instances? (Was: Why DataView.prototype object's [[Class]] is Object?))

2012-10-02 Thread Brendan Eich

Herby Vojčík wrote:

It can be `arguments.isConstruct`, for example.


(One-handed Luke Skywalker voice:) NOo

/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-02 Thread Kevin Smith
 On the other hand, if you have many instances that need to be branded I
 suspect that the distributed symbol based technique is going to have a
 better performance profile than the WeakMaps.


Is this true?  Are there performance caveats that come with current
WeakMap implementations?

Kevin
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Test for [[Construct]] invocation (was: Re: Must built-in prototypes also be valid instances? (Was: Why DataView.prototype object's [[Class]] is Object?))

2012-10-02 Thread Herby Vojčík



Brendan Eich wrote:

Herby Vojčík wrote:

It can be `arguments.isConstruct`, for example.


(One-handed Luke Skywalker voice:) NOo
Or whatever else, I just happened to write first thing where it could 
reside.


/be

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Test for [[Construct]] invocation (was: Re: Must built-in prototypes also be valid instances? (Was: Why DataView.prototype object's [[Class]] is Object?))

2012-10-02 Thread Kevin Smith
 (One-handed Luke Skywalker voice:) NOo


: ) Another perfect response!

Kevin
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-02 Thread Mark S. Miller
On Tue, Oct 2, 2012 at 11:01 AM, Allen Wirfs-Brock al...@wirfs-brock.comwrote:


 On Oct 2, 2012, at 10:18 AM, Kevin Smith wrote:


 private @FooBrand;
 class Foo {
constructor() {
 /* establish the internal Fooness of the instance */
 this.@FooBrand = true;
}
 }
 Foo.isFoo = function (obj) {return !!obj.@FooBrand};


 Using this strategy, will isFoo not fail, if the specified object came
 from a different global context (frame)?

 Kevin


 Indeed it would, but why shouldn't it?  Foo in another  frame is a
 different class.  If you need to do cross-frame brand, that seems like an
 additional requirement would require additional mechanism.

 Wouldn't a WeakMap branding scheme has similar issues. You would need to
 share via some means a common WeakMap among constructors in different
 frames.  Just like to make symbol based branding work for this requirement
 you would have to share a private symbol between frames.

 For classes, I agree it should fail cross frame -- they are different
classes. But what about builtins? Note that ES5 [[Class]] is a cross-frame
brand for builtins. And Array.isArray is an ad-hoc one-off cross-frame
brand check.




 Allen





-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-02 Thread Allen Wirfs-Brock

On Oct 2, 2012, at 2:46 PM, Mark S. Miller wrote:

 
 
 On Tue, Oct 2, 2012 at 11:01 AM, Allen Wirfs-Brock al...@wirfs-brock.com 
 wrote:
 
 On Oct 2, 2012, at 10:18 AM, Kevin Smith wrote:
 
 
 private @FooBrand;
 class Foo {
constructor() {
 /* establish the internal Fooness of the instance */
 this.@FooBrand = true;
}
 }
 Foo.isFoo = function (obj) {return !!obj.@FooBrand};
 
 Using this strategy, will isFoo not fail, if the specified object came from 
 a different global context (frame)?
 
 Kevin
 
 
 Indeed it would, but why shouldn't it?  Foo in another  frame is a different 
 class.  If you need to do cross-frame brand, that seems like an additional 
 requirement would require additional mechanism.
 
 Wouldn't a WeakMap branding scheme has similar issues. You would need to 
 share via some means a common WeakMap among constructors in different frames. 
  Just like to make symbol based branding work for this requirement you would 
 have to share a private symbol between frames.
 
 For classes, I agree it should fail cross frame -- they are different 
 classes. But what about builtins? Note that ES5 [[Class]] is a cross-frame 
 brand for builtins. And Array.isArray is an ad-hoc one-off cross-frame brand 
 check.


If you take a look at the recent draft spec. for Map you will see that is uses 
an internal branding check that is supposed to work across frame.   If that 
check is properly implemented then one can code 

function isBuiltinMap(obj) {
   try {
   Map.prototype.size.call(obj)
   } catch (e) {return false};
   return true;
}


But this does raise an interesting question for self-host built-in and for any 
user self hosted class definitions.

The spec leaves it up to the Map implementation to define the mechanism for 
testing for the presence of [[MapData]]. But, in an ES self hosted 
implementation a private symbol or WeakMap registry  are probably the two most 
plausible available mechanisms.   Both of these would require some secure 
mechanism for cross frame sharing in order make the branding work cross frame.  
I don't think we currently have this.  Perhaps it is a module loader issue.  Or 
perhaps it is an implementation issue.  If built-ins have magic powers and the 
implementation wants to support self hosting of built-in then perhaps it's the 
implementation responsibility to provide the mechanism for granting those 
powers. 

Allen___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-02 Thread Norbert Lindenberg
TC 39, I need decisions so that I can finish the Internationalization spec and 
send it to the Ecma GA:

1) Instances of Intl.Collator, Intl.NumberFormat, and Intl.DateTimeFormat 
currently have [[Class]] Object. Should this change to Collator, 
NumberFormat, and DateTimeFormat, respectively?

2) If the answer to 1) is yes: The prototype objects of Intl.Collator, 
Intl.NumberFormat, and Intl.DateTimeFormat currently have [[Class]] Object. 
Should this change to Collator, NumberFormat, and DateTimeFormat, 
respectively?

3) If the answer to 1) or 2) is no: The prototype objects of Intl.Collator, 
Intl.NumberFormat, and Intl.DateTimeFormat currently have all the state that 
allows them to be used as instances. Should they not have that state, and 
instead be plain objects with methods?

If I don't get votes from at least 10 of the usual TC 39 attendees within the 
next 24 hours, and a clear majority for change, the spec will remain as 
approved at the meeting two weeks ago.

Thanks,
Norbert


On Sep 29, 2012, at 23:08 , Brendan Eich wrote:

 Norbert Lindenberg wrote:
 Last week TC 39 approved a standard defining three new built-in constructors 
 whose instances and prototype objects all have [[Class]] Object. Also, the 
 prototype objects are not constructed by their respective constructors, but 
 initialized by them, e.g., as Intl.Collator.call({}).
 
 Are you suggesting they should have Collator, NumberFormat, and 
 DateTimeFormat, respectively, and the prototypes be specified as being 
 constructed by their constructors?
 
 All else equal, yes (sorry for not flagging these).
 
 Any non-equal elses in sight?
 
 /be

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-02 Thread Brendan Eich
At this point I'd go with Object (IOW, _stet_), unless Allen has a 
thought.


/be

Norbert Lindenberg wrote:
TC 39, I need decisions so that I can finish the Internationalization spec and send it to the Ecma GA: 



1) Instances of Intl.Collator, Intl.NumberFormat, and Intl.DateTimeFormat currently have [[Class]] Object. Should this change to Collator, NumberFormat, and DateTimeFormat, respectively? 



2) If the answer to 1) is yes: The prototype objects of Intl.Collator, Intl.NumberFormat, and Intl.DateTimeFormat currently have [[Class]] Object. Should this change to Collator, NumberFormat, and DateTimeFormat, respectively? 



3) If the answer to 1) or 2) is no: The prototype objects of Intl.Collator, Intl.NumberFormat, and Intl.DateTimeFormat currently have all the state that allows them to be used as instances. Should they not have that state, and instead be plain objects with methods? 



If I don't get votes from at least 10 of the usual TC 39 attendees within the next 24 hours, and a clear majority for change, the spec will remain as approved at the meeting two weeks ago. 



Thanks,
Norbert


On Sep 29, 2012, at 23:08 , Brendan Eich wrote:


Norbert Lindenberg wrote:
Last week TC 39 approved a standard defining three new built-in constructors whose instances and prototype objects all have [[Class]] Object. Also, the prototype objects are not constructed by their respective constructors, but initialized by them, e.g., as Intl.Collator.call({}). 



Are you suggesting they should have Collator, NumberFormat, and DateTimeFormat, respectively, and the prototypes be specified as being constructed by their constructors? 


All else equal, yes (sorry for not flagging these).

Any non-equal elses in sight?

/be


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-02 Thread Allen Wirfs-Brock

On Oct 2, 2012, at 9:46 PM, Brendan Eich wrote:

 At this point I'd go with Object (IOW, _stet_), unless Allen has a thought.

I agree.

Regarding 3, if it is easy spec-wide to make the prototype non-instances that 
would be preferable, but as long as the per instance state in the prototype is 
immutable I think it would be ok leaving it as currently specified.

Allen


 
 /be
 
 Norbert Lindenberg wrote:
 TC 39, I need decisions so that I can finish the Internationalization spec 
 and send it to the Ecma GA: 
 
 1) Instances of Intl.Collator, Intl.NumberFormat, and Intl.DateTimeFormat 
 currently have [[Class]] Object. Should this change to Collator, 
 NumberFormat, and DateTimeFormat, respectively? 
 
 2) If the answer to 1) is yes: The prototype objects of Intl.Collator, 
 Intl.NumberFormat, and Intl.DateTimeFormat currently have [[Class]] 
 Object. Should this change to Collator, NumberFormat, and 
 DateTimeFormat, respectively? 
 
 3) If the answer to 1) or 2) is no: The prototype objects of 
 Intl.Collator, Intl.NumberFormat, and Intl.DateTimeFormat currently have all 
 the state that allows them to be used as instances. Should they not have 
 that state, and instead be plain objects with methods? 
 
 If I don't get votes from at least 10 of the usual TC 39 attendees within 
 the next 24 hours, and a clear majority for change, the spec will remain as 
 approved at the meeting two weeks ago. 
 
 Thanks,
 Norbert
 
 
 On Sep 29, 2012, at 23:08 , Brendan Eich wrote:
 
 Norbert Lindenberg wrote:
 Last week TC 39 approved a standard defining three new built-in 
 constructors whose instances and prototype objects all have [[Class]] 
 Object. Also, the prototype objects are not constructed by their 
 respective constructors, but initialized by them, e.g., as 
 Intl.Collator.call({}). 
 
 Are you suggesting they should have Collator, NumberFormat, and 
 DateTimeFormat, respectively, and the prototypes be specified as being 
 constructed by their constructors? 
 All else equal, yes (sorry for not flagging these).
 
 Any non-equal elses in sight?
 
 /be
 
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss
 
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss
 

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Andreas Rossberg
On 30 September 2012 02:17, Brendan Eich bren...@mozilla.org wrote:
 Failing to consult with implementors will just make editing churn. I don't
 remember much discussion on this change, if any -- we did talk about the
 general problem of prototype objects being firstborns of their class, and
 how this makes them sometimes not just basis cases but degenerate cases.

 However, Map is prototyped in SpiderMonkey and V8. In SpiderMonkey, the
 prototype is a Map, not an Object:

Er, from my reading that's clearly not what the Wiki says for WeakMap.
And it also is not what V8 implements, for either WeakMap or Map.


 js Object.prototype.toString.call(Map.prototype).slice(8, -1)
 Map

 but you can't get, has, set, size, or iterate Map.prototype:

 js Map.prototype.get('x')
 typein:2:0 TypeError: get method called on incompatible Map
 js Map.prototype.has('x')
 typein:3:0 TypeError: has method called on incompatible Map
 js Map.prototype.set('x', 42)
 typein:4:0 TypeError: set method called on incompatible Map
 js Map.prototype.size()
 typein:5:0 TypeError: size method called on incompatible Map
 js for (var [k, v] of Map.prototype) ;
 typein:6:13 TypeError: iterator method called on incompatible Map

 The error message is suboptimal but what's going on here is that
 Map.prototype has the SpiderMonkey equivalent of [[Class]] == Map (or the
 ES6 equivalent). This is important since all the builtins in ES3 + Reality
 (including RegExp; ES3 deviated there) make the prototype for built-in class
 C be of class C.

 Your change requires implementations to provide a different built-in class
 (constructor/prototype) initialization path. That's not desirable _per se_.
 Neither IMHO is the user-facing semantic split among old and new
 constructors.

 There are two separate issues here:

 1. Should Map.prototype be an instance (firstborn for its realm) of class
 Map?

 2. Should Map.prototype be a key/value store that can be used or abused as
 any other Map could be?

 We should not mix these up. SpiderMonkey (and possibly V8, I haven't tested)
 says yes to 1 and no to 2.

V8 says no to both. And I fail to see what benefit there is to
separating the two. In fact, it seems hostile to programmers to do so.

I think Allen is absolutely right that the magic incest of current
built-ins is not going to scale, is semantically questionable, and
should best be abandoned.


I did not specify that Map.prototype is a Map instance.  While it has
 the methods that are applicable to Map instances it does not the internal
 state that is necessary for those methods to actually work.  For example, if
 you try to store a value into Map.prototype by calling its set method, you
 will get a TypeErrior according to the specification. May.prototype can not
 be used as a map object.

 That doesn't mean Map.prototype should not be classified as a Map per 1
 above.

But seriously, what's the advantage of doing otherwise? What purpose
would it serve? I must be missing something.

/Andreas
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Kevin Smith
 I think Allen is absolutely right that the magic incest of current
 built-ins is not going to scale, is semantically questionable, and
 should best be abandoned.


: )  magic incest.  This is pretty much a perfect response.

Kevin
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Oliver Hunt

 
 V8 says no to both. And I fail to see what benefit there is to
 separating the two. In fact, it seems hostile to programmers to do so.
 
 I think Allen is absolutely right that the magic incest of current
 built-ins is not going to scale, is semantically questionable, and
 should best be abandoned.

Agreed, the pattern of FooPrototype being an instance of Foo makes things more 
complicated for no obvious reason, and is only really used by conformance 
suites anyway :D

I see no reason ever create a new type that has screwy prototype/instance 
magic, the existing cases only get in by virtue of dubious backwards 
compatibility claims.

--Oliver
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Erik Arvidsson
On Sun, Sep 30, 2012 at 1:14 AM, Brendan Eich bren...@mozilla.org wrote:
 V8 and SpiderMonkey agree. This avoids making two paths for built-in
 constructor.prototype creation, one that makes a degenerate firstborn of the
 class at hand, the other than makes an Object-instance prototype.

V8 disagrees (like Andreas also pointed out):

 Object.prototype.toString.call(Map.prototype)
'[object Object]'
 Map.prototype.set(1, 2)
TypeError: Method Map.prototype.set called on incompatible receiver #Map

I'm with Allen, Andreas and others that the craziness needs to stop.


-- 
erik
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Brendan Eich

Andreas Rossberg wrote:
Er, from my reading that's clearly not what the Wiki says for WeakMap. 
And it also is not what V8 implements, for either WeakMap or Map. 


Sorry, I was relying on Rick's testimony that the answers were 1) yes, 
2) no.



V8 says no to both. And I fail to see what benefit there is to
separating the two. In fact, it seems hostile to programmers to do so.


Either way, something splits. 1/2 = y/n requires a degenerate prototype 
of same class. 1/2 = n/n requires a split from all the ES5 and prior 
built-ins.



I think Allen is absolutely right that the magic incest of current
built-ins is not going to scale, is semantically questionable, and
should best be abandoned.


Could you say a bit more?

There's a scaling problem indeed if each new class must enforce the 
degenerate prototype case with extra code. Using an Object instance to 
hold methods is a fixed extra cost (the split from all the ES5 and 
prior built-ins cost). Granted, implementations will have to do some 
work for the new classes that might hold mutable state. But they can 
systematize internally so this is not a new custom work each time a 
class with mutable state is added.


The best reason for using Object is the one Mark raised: class (as sugar 
for constructor/prototype) uses Object.


But if you've read the thread this far, my objective is not to enforce 
one implementation approach or the other. It's to use @@toStringTag and 
anything like it so there's no observable difference between the two 
approaches. Classes should be able to do likewise.


Otherwise we have

  class C extends B {...}

and

  C.prototype instanceof Object

when the cowpath today wants

  C.prototype instanceof B

/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Brendan Eich

Nah, cheap shot. Let's reason together, not join taboo words.

The built-ins do what they do and it could be considered a botch to 
abandon, but then there's still a scar lying between old and new 
built-ins. And classes have to do one or both (we may want to self-host 
built-ins with classes).


Thus the quest (not mine alone) to make it unobservable whether the 
builtin constructor's prototype is a degenerate firstborn or a 
dressed-up Object instance.


/be

Kevin Smith wrote:


I think Allen is absolutely right that the magic incest of current
built-ins is not going to scale, is semantically questionable, and
should best be abandoned.


: )  magic incest.  This is pretty much a perfect response.

Kevin
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Brendan Eich

Oliver Hunt wrote:

  FooPrototype being an instance of Foo makes things more complicated for no 
obvious reason, and is only really used by conformance suites anyway :D


That's true enough.

The dubious backward compatibility claims are what they are, though, and 
try inducting a bit: class C extends B {}. What is C.prototype an 
instance of?


/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Brendan Eich

Allen Wirfs-Brock wrote:
Line 5.c.v is dealing with the ES5 requirement that host objects not 
reuse the listed [[Class]] values for anything other than the 
specified built-ins. This version of toStrimg extends the spirit to 
that restriction to all user or implementation defined tag values.  It 
does this by prepending a ~ in front of those values if they appear 
as a tag value.  Note that ES5.1 includes Object in this list so I 
also included it. But, I actually think it probably should be in the 
censored list.


This is weird.

ES5 wanted to help SES and similar languages use some kind of

  original_Object_prototype_toString_call(anyObject).slice(8,-1)

and not be subject to spoofing.

Adding @@toStringTag to enable DOM self-hosting runs directly counter to 
this goal.


Prefixing ~ to core-language built-in classes (save Object?) does 
not resolve the conflict if there are spoofing hazards in other 
built-ins such as DOM objects as typically implemented in browsers.


Mark, can you weigh in? I had not heard of this ~-prefixing idea.

/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Rick Waldron
On Mon, Oct 1, 2012 at 3:21 PM, Brendan Eich bren...@mozilla.com wrote:

 Andreas Rossberg wrote:

 Er, from my reading that's clearly not what the Wiki says for WeakMap.
 And it also is not what V8 implements, for either WeakMap or Map.


 Sorry, I was relying on Rick's testimony that the answers were 1) yes, 2)
 no.



Yes, when I first considered the topic, it seemed to make some kind of
sense (based on a desire for consistency), but I also don't believe that
should be the case now—I even noted that I had always subjectively viewed
resulting behaviours as strange.

I'm not sure I've ever encountered code in the wild that made any
intentional use of built-ins Foo.prototype-as-firstborn - can anyone on the
list point to some compelling use cases?


Rick
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Erik Arvidsson
On Mon, Oct 1, 2012 at 3:30 PM, Brendan Eich bren...@mozilla.com wrote:
 Erik Arvidsson wrote:

 I'm with Allen, Andreas and others that the craziness needs to stop.


 Which craziness?

That the prototype of the constructor needs to be a special case of
the instances created by the constructor.

Today, both new Date and Date.prototype are date objects. I think
this just makes things more complicated for no apparent gain.

-- 
erik
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Brendan Eich

Rick Waldron wrote:
On Mon, Oct 1, 2012 at 3:21 PM, Brendan Eich bren...@mozilla.com 
mailto:bren...@mozilla.com wrote:


Andreas Rossberg wrote:

Er, from my reading that's clearly not what the Wiki says for
WeakMap. And it also is not what V8 implements, for either
WeakMap or Map.


Sorry, I was relying on Rick's testimony that the answers were 1)
yes, 2) no.



Yes, when I first considered the topic, it seemed to make some kind of 
sense (based on a desire for consistency), but I also don't believe 
that should be the case now—I even noted that I had always 
subjectively viewed resulting behaviours as strange.


Oops, then I really misread one of your messages -- I thought you had 
tested in V8.


I'm not sure I've ever encountered code in the wild that made any 
intentional use of built-ins Foo.prototype-as-firstborn - can anyone 
on the list point to some compelling use cases?


If it doesn't matter, we could make all the built-ins' 
constructor.prototype objects be instances of Object (except for the 
Error subclasses!).


That would be nice. Then we'd have

  class C extends B {}
  assert(C.prototype instanceof B)

and per Allen's nifty trick of avoiding class-side inheritance from 
Object (which made Dave hear angels sing):


  class C {}
  assert(C.prototype instanceof Object)

/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Brendan Eich

Erik Arvidsson wrote:

On Mon, Oct 1, 2012 at 3:30 PM, Brendan Eichbren...@mozilla.com  wrote:

Erik Arvidsson wrote:

I'm with Allen, Andreas and others that the craziness needs to stop.

Which craziness?


That the prototype of the constructor needs to be a special case of
the instances created by the constructor.

Today, both new Date and Date.prototype are date objects. I think
this just makes things more complicated for no apparent gain.


Yes, and it makes that side channel that vexed Mark and SES (Caja).

Can we change incompatibly? Rick just asked what code relies on builtins 
being firstborns. No one relies on degenerate firstborns except by 
toString tag testing.


/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Rick Waldron
On Mon, Oct 1, 2012 at 4:04 PM, Brendan Eich bren...@mozilla.com wrote:

 Rick Waldron wrote:

  On Mon, Oct 1, 2012 at 3:21 PM, Brendan Eich bren...@mozilla.commailto:
 bren...@mozilla.com wrote:

 Andreas Rossberg wrote:

 Er, from my reading that's clearly not what the Wiki says for
 WeakMap. And it also is not what V8 implements, for either
 WeakMap or Map.


 Sorry, I was relying on Rick's testimony that the answers were 1)
 yes, 2) no.



 Yes, when I first considered the topic, it seemed to make some kind of
 sense (based on a desire for consistency), but I also don't believe that
 should be the case now—I even noted that I had always subjectively viewed
 resulting behaviours as strange.


 Oops, then I really misread one of your messages -- I thought you had
 tested in V8.


I did, via node, but I was showing Array, not Map—Erik showed Map, which is
the built-in that disagrees :)




  I'm not sure I've ever encountered code in the wild that made any
 intentional use of built-ins Foo.prototype-as-firstborn - can anyone on the
 list point to some compelling use cases?


 If it doesn't matter, we could make all the built-ins'
 constructor.prototype objects be instances of Object (except for the Error
 subclasses!).


Is there any way to confirm?


Rick



 That would be nice. Then we'd have

   class C extends B {}
   assert(C.prototype instanceof B)

 and per Allen's nifty trick of avoiding class-side inheritance from Object
 (which made Dave hear angels sing):

   class C {}
   assert(C.prototype instanceof Object)








 /be

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Allen Wirfs-Brock

On Oct 1, 2012, at 12:21 PM, Brendan Eich wrote:
...
 The best reason for using Object is the one Mark raised: class (as sugar for 
 constructor/prototype) uses Object.
 
 But if you've read the thread this far, my objective is not to enforce one 
 implementation approach or the other. It's to use @@toStringTag and anything 
 like it so there's no observable difference between the two approaches. 
 Classes should be able to do likewise.
 
 Otherwise we have
 
  class C extends B {...}
 
 and
 
  C.prototype instanceof Object
 
 when the cowpath today wants
 
  C.prototype instanceof B

I'm not sure  what you are arguing for/against with the above point about 
instanceof.  

instanceof is it's own mechanism that is independent of toString,  [[Class]] 
tagging, or any concept that is used in section 15 of  ES=5.1 when it is 
talking about instances of the various built-ins.  About the best you can do is 
create a table that compares all the various mechanism that do something like 
an instance of check against the actual built-in and look for the 
consistencies/inconsistencies. 

The current spec. language for class definitions would produce true for 
C.prototype instanceof B and false for C.prototype instanceof C.  But it would 
also answer true for C.prototype instanceof Object and B.prototype instanceof 
Object.

If there is an inconsistency here, it is that C.prototype claims to be 
instanceof B but in fact probably hasn't been initialized using the B 
constructor so it can't actually behave as a B instance.

Allen


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Allen Wirfs-Brock

On Oct 1, 2012, at 12:39 PM, Brendan Eich wrote:

 Allen Wirfs-Brock wrote:
 Line 5.c.v is dealing with the ES5 requirement that host objects not reuse 
 the listed [[Class]] values for anything other than the specified built-ins. 
 This version of toStrimg extends the spirit to that restriction to all user 
 or implementation defined tag values.  It does this by prepending a ~ in 
 front of those values if they appear as a tag value.  Note that ES5.1 
 includes Object in this list so I also included it. But, I actually think 
 it probably should be in the censored list.
 
 This is weird.
 
 ES5 wanted to help SES and similar languages use some kind of
 
  original_Object_prototype_toString_call(anyObject).slice(8,-1)
 
 and not be subject to spoofing.
 
 Adding @@toStringTag to enable DOM self-hosting runs directly counter to this 
 goal.
 
 Prefixing ~ to core-language built-in classes (save Object?) does not 
 resolve the conflict if there are spoofing hazards in other built-ins such as 
 DOM objects as typically implemented in browsers.
 
 Mark, can you weigh in? I had not heard of this ~-prefixing idea.

Let me try explaining this again, if we provide an extension point for 
parameterizing Object.prototype.toString and it allows arbitrary objects to 
produce, for example, [Object Array]
 or [Object Function] then it invalidates all legacy uses of 
Object.prototype.toString as nominal type check for those specific built-ins.  
The ~ prefix is one way to avoid this problem.

DOM implementation usage is a separate issue, although arguably a motivating 
one making Object.prototype.toString extensible.  W3C specifications have 
consistently tried to use [[Class]] as an extension point for parameterizing 
Object.prototype.toString and implementations have supported them by providing 
implementation specific mechanisms that allow DOM implementations provide a 
[[Class]] value to Object.prototype.toString.

The proposed ES6 spec. for Object.prototype.toString recognizes the utility of 
such an extension point.  I would certainly be used by a ES-host DOM 
implementation but it would also be useful  for anyone else defining class-like 
abstractions where they want Object.prototype.toString.

The little quicks like the ~ prefix and the exception eating are simply what 
is necessary to formalize this extensibility model while still preserving the 
behavior of existing code that depends upon object.prototype.toString as a 
reliable mechanism to test for instances of the ES=5.1 built-ins.

Allen
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Norbert Lindenberg
It might be useful to list all the observable features to which valid instance 
of might lead for a built-in BuiltIn.prototype, and check whether we want them 
for new built-ins:

1) Object.prototype.toString.call(BuiltIn.prototype) returns [object BuiltIn].

True for ES5 objects, currently not true for ES Internationalization objects. 
Discussion so far inconclusive.

2) BuiltIn.prototype has state that lets BuiltIn methods successfully operate 
on the object, at least as long as they don't modify the state.

True for ES5 objects, currently also true for ES Internationalization objects. 
This means Intl.Collator.prototype can be used as a Collator with default 
properties, which applications might find useful. Discussion so far 
inconclusive.

3) The state mentioned in 2) is modifiable.

True for some ES5 objects (Array, Date, RegExp), not true for ES 
Internationalization objects. The discussion seems to conclude that modifiable 
prototype objects are a bad idea.

4) Object.getPrototypeOf(BuiltIn.prototype) returns BuiltIn.prototype.

False for ES5 objects and ES Internationalization objects. This would lead to 
infinite loops when looking up properties that don't exist, and we probably 
don't want that.

5) BuiltIn.prototype instanceof BuiltIn evaluates to true.

False for ES5 objects and ES Internationalization objects. The ES5 spec for 
instanceof relies on 4).

Any observable features I missed?

Norbert

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Allen Wirfs-Brock

On Oct 1, 2012, at 2:44 PM, Norbert Lindenberg wrote:

 It might be useful to list all the observable features to which valid 
 instance of might lead for a built-in BuiltIn.prototype, and check whether 
 we want them for new built-ins:
 
 1) Object.prototype.toString.call(BuiltIn.prototype) returns [object 
 BuiltIn].
 
 True for ES5 objects, currently not true for ES Internationalization objects. 
 Discussion so far inconclusive.

Also not true for: EvalError, RangeError, ReferenceError, SyntaxError, 
TypeError, and URIError

they are all spec'd to return [object Error] from toString

 
 2) BuiltIn.prototype has state that lets BuiltIn methods successfully operate 
 on the object, at least as long as they don't modify the state.
 
 True for ES5 objects, currently also true for ES Internationalization 
 objects. This means Intl.Collator.prototype can be used as a Collator with 
 default properties, which applications might find useful. Discussion so far 
 inconclusive.
 
 3) The state mentioned in 2) is modifiable.
 
 True for some ES5 objects (Array, Date, RegExp), not true for ES 
 Internationalization objects. The discussion seems to conclude that 
 modifiable prototype objects are a bad idea.
 
 4) Object.getPrototypeOf(BuiltIn.prototype) returns BuiltIn.prototype.
 
 False for ES5 objects and ES Internationalization objects. This would lead to 
 infinite loops when looking up properties that don't exist, and we probably 
 don't want that.
 
 5) BuiltIn.prototype instanceof BuiltIn evaluates to true.
 
 False for ES5 objects and ES Internationalization objects. The ES5 spec for 
 instanceof relies on 4).
 
 Any observable features I missed?

The relationship between the constructor and the prototype.  EG:  
Builtin.prototype.constructor === Builtin


 
 Norbert
 
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss
 

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Brendan Eich

Allen Wirfs-Brock wrote:

On Oct 1, 2012, at 12:21 PM, Brendan Eich wrote:
...

The best reason for using Object is the one Mark raised: class (as sugar for 
constructor/prototype) uses Object.

But if you've read the thread this far, my objective is not to enforce one 
implementation approach or the other. It's to use @@toStringTag and anything 
like it so there's no observable difference between the two approaches. Classes 
should be able to do likewise.

Otherwise we have

  class C extends B {...}

and

  C.prototype instanceof Object

when the cowpath today wants

  C.prototype instanceof B


I'm not sure  what you are arguing for/against with the above point about 
instanceof.


I'm not arguing for or against yet, just observing that we can't 
rule out the possibility that a class constructor.prototype is *not* a 
plain old Object instance, and (if B has mutable state hidden behind 
accessors) presents the side channel Mark pointed out.



instanceof is it's own mechanism that is independent of toString,  [[Class]] tagging, or any 
concept that is used in section 15 of  ES=5.1 when it is talking about instances of the 
various built-ins.  About the best you can do is create a table that compares all the 
various mechanism that do something like an instance of check against the actual 
built-in and look for the consistencies/inconsistencies.


Yes, the toString tagging is separate and can be handled (we should 
decide how it should be handled, though. Is C.prototype.constructor === 
C even though C.prototype instanceof B not C?).


The side channel issue remains.


The current spec. language for class definitions would produce true for 
C.prototype instanceof B and false for C.prototype instanceof C.


Right, and this is saner than the builtins which also have !(C.prototype 
instanceof C) but also tag such that TagOf(C.prototype) === C.



   But it would also answer true for C.prototype instanceof Object and 
B.prototype instanceof Object.


One would hope so! :-P


If there is an inconsistency here, it is that C.prototype claims to be 
instanceof B but in fact probably hasn't been initialized using the B 
constructor so it can't actually behave as a B instance.


FWIW, here's what CoffeeScript generates:

(function() {
  var B, C,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if 
(__hasProp.call(parent, key)) child[key] = parent[key]; } function 
ctor() { this.constructor = child; } ctor.prototype = parent.prototype; 
child.prototype = new ctor(); child.__super__ = parent.prototype; return 
child; };


  B = (function() {

function B() {}

B.prototype.p = 42;

return B;

  })();

  C = (function(_super) {

__extends(C, _super);

C.prototype.q = 99;

function C(p, q) {
  this.p = p;
  this.q = q;
}

return C;

  })(B);

  console.log(C.prototype instanceof B);

}).call(this);


The __extends function copies class-side heritables but then sets 
child.prototype = new ctor(), so interposes a new Object instance with 
shadowing constructor =  child in between child.prototype and 
parent.prototype.


This is just informative, but now that I look at it, it seems to me to 
avoid the mutable state side channel, provided B.prototype is 
(inductively) an Object instance. Neat!


/be


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Brendan Eich

Allen Wirfs-Brock wrote:

On Oct 1, 2012, at 12:39 PM, Brendan Eich wrote:


Allen Wirfs-Brock wrote:

Line 5.c.v is dealing with the ES5 requirement that host objects not reuse the listed [[Class]] 
values for anything other than the specified built-ins. This version of toStrimg extends the spirit to that 
restriction to all user or implementation defined tag values.  It does this by prepending a ~ in 
front of those values if they appear as a tag value.  Note that ES5.1 includes Object in this 
list so I also included it. But, I actually think it probably should be in the censored list.

This is weird.

ES5 wanted to help SES and similar languages use some kind of

  original_Object_prototype_toString_call(anyObject).slice(8,-1)

and not be subject to spoofing.

Adding @@toStringTag to enable DOM self-hosting runs directly counter to this 
goal.

Prefixing ~ to core-language built-in classes (save Object?) does not 
resolve the conflict if there are spoofing hazards in other built-ins such as DOM objects as 
typically implemented in browsers.

Mark, can you weigh in? I had not heard of this ~-prefixing idea.


Let me try explaining this again,


No need to rehash.

Responding to my point about other legacy tag tests that are not 
twiddled with ~ and so are possibly invalidated would be helpful. 
*Why* are the core language names sacrosanct when tag-testing of other 
class names is also potentially just as important, e.g., for SES?



The little quicks like the ~ prefix and the exception eating are simply what 
is necessary


Not so fast there, Tex!

First, *something* is necessary for preserving certain names from being 
spoofed and invalidating a tag-test, but we should agree on the names 
and the reason for spoof-proofing exactly and only that set of names.


Second, eating exceptions does *not* follow from what is necessary 
even if I agree with your set of names! Eating exceptions is bad on 
principle. Why do you do it here? A host object might throw on attempt 
to get a novel property name such as @@toStringTag but is that an actual 
concern?


Also, I'm assuming the ??? strings are just place-holders. True?


  to formalize this extensibility model while still preserving the behavior of 
existing code that depends upon object.prototype.toString as a reliable mechanism 
to test for instances of the ES=5.1 built-ins.


Adding new internal method calls with novel ids might add new exception 
throws. That's part of the package deal.


Implementors control their host objects in general and can tame any that 
might throw on @@toStringTag [[Get]]. Suppose an implementation has a 
bug where such a throw happens, for any reason (could be the novel 
symbol property-name, or could be some other reason). Suppressing 
prevents anyone (implementor, developer, us) from knowing what is going on.


I'm laboring over this because in JS1 I suppressed exceptions trying 
toString and valueOf and that bit back. [[DefaultValue]] uses 
ReturnIfAbrupt which propagates the abrupt completion rather than 
dropping it on the floor.


/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Brendan Eich

Norbert Lindenberg wrote:

It might be useful to list all the observable features to which valid instance 
of might lead for a built-in BuiltIn.prototype, and check whether we want them for 
new built-ins:

1) Object.prototype.toString.call(BuiltIn.prototype) returns [object BuiltIn].

True for ES5 objects, currently not true for ES Internationalization objects. 
Discussion so far inconclusive.


Fair enough.


2) BuiltIn.prototype has state that lets BuiltIn methods successfully operate 
on the object, at least as long as they don't modify the state.

True for ES5 objects, currently also true for ES Internationalization objects. 
This means Intl.Collator.prototype can be used as a Collator with default 
properties, which applications might find useful. Discussion so far 
inconclusive.


Mark has a conclusion: don't hide mutable state behind accessors in a 
prototype. The reason is that Object.freeze can't freeze such state. Is 
Intl.Collator.prototype's state hidden that way, or exposed to 
Object.freeze?



3) The state mentioned in 2) is modifiable.

True for some ES5 objects (Array, Date, RegExp),


Don't forget Object :-P.


  not true for ES Internationalization objects. The discussion seems to 
conclude that modifiable prototype objects are a bad idea.


I'm not sure -- I would say the known problem is hidden (to 
Object.freeze) mutable state, not data properties such as 
RegExp.lastIndex. Mark should confirm.



4) Object.getPrototypeOf(BuiltIn.prototype) returns BuiltIn.prototype.

False for ES5 objects and ES Internationalization objects. This would lead to 
infinite loops when looking up properties that don't exist, and we probably 
don't want that.


Yes, this makes no sense, not a goal in any scenario.


5) BuiltIn.prototype instanceof BuiltIn evaluates to true.

False for ES5 objects and ES Internationalization objects. The ES5 spec for 
instanceof relies on 4).]]


Indeed this cannot be true given that o instanceof C always gets o's 
[[Prototype]] before matching against C.prototype -- always hops one up 
the chain.



Any observable features I missed?


I think that's it. I hope so!

/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Brendan Eich

Allen Wirfs-Brock wrote:

Any observable features I missed?


The relationship between the constructor and the prototype.  EG:  
Builtin.prototype.constructor === Builtin


Right! I forgot this a minute ago after showing how CoffeeScript does 
it. D'oh.


I am warming up to the way CoffeeScript does things -- not the 
translation scheme, __extends, __super__ -- rather, the plain Object 
instance created as C.prototype that has B.prototype as its 
[[Prototype]] but has shadowing 'constructor' set to C.


With a rule to set @@toStringTag by default (or not), and some attempt 
to match legacy built-ins (I'm thinking about trying this on in 
SpiderMonkey), we might have a regular set of rules for this stuff.


The safest course might still be to set @@toStringTag to C in 
C.prototype, along with 'constructor'. That would fake things up to 
match legacy built-ins except where they provide a communication channel.


I'd still want to close that channel, by making Date.prototype a 
dressed-up Object instance. But this would be less risky than making its 
tag-testable class name be Object.


/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Domenic Denicola
On Oct 1, 2012, at 18:58, Brendan Eich bren...@mozilla.org wrote:

 I am warming up to the way CoffeeScript does things -- not the translation 
 scheme, __extends, __super__ -- rather, the plain Object instance created as 
 C.prototype that has B.prototype as its [[Prototype]] but has shadowing 
 'constructor' set to C.

If I'm understanding correctly, this would be the same as

C.prototype = Object.create(B.prototype);
C.prototype.constructor = C;

which I thought was the recommended approach (although by who or where, I 
admit I can't quite pinpoint). Am I on the right track? And can anyone else 
comment on the commonality or recommendedness of this pattern, to see if we're 
paving the right cow paths?
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Brendan Eich

Domenic Denicola wrote:

On Oct 1, 2012, at 18:58, Brendan Eichbren...@mozilla.org  wrote:


I am warming up to the way CoffeeScript does things -- not the translation 
scheme, __extends, __super__ -- rather, the plain Object instance created as 
C.prototype that has B.prototype as its [[Prototype]] but has shadowing 
'constructor' set to C.


If I'm understanding correctly, this would be the same as

C.prototype = Object.create(B.prototype);
C.prototype.constructor = C;


Yes, CoffeeScript simply uses the older pattern (beget, goes back a long 
way to comp.lang.javascript, IIRC) to work on pre-ES5 engines.



which I thought was the recommended approach (although by who or where, I 
admit I can't quite pinpoint). Am I on the right track? And can anyone else comment on 
the commonality or recommendedness of this pattern, to see if we're paving the right cow 
paths?


Would be good to confirm, but I think this is the one all the finest 
cows favor ;-).


/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Brendan Eich

Brendan Eich wrote:

Erik Arvidsson wrote:
On Mon, Oct 1, 2012 at 3:30 PM, Brendan Eichbren...@mozilla.com  
wrote:

Erik Arvidsson wrote:

I'm with Allen, Andreas and others that the craziness needs to stop.

Which craziness?


That the prototype of the constructor needs to be a special case of
the instances created by the constructor.

Today, both new Date and Date.prototype are date objects. I think
this just makes things more complicated for no apparent gain.


Yes, and it makes that side channel that vexed Mark and SES (Caja).

Can we change incompatibly? Rick just asked what code relies on 
builtins being firstborns. No one relies on degenerate firstborns 
except by toString tag testing.


Just to be super-clear:

1. I agree the built-ins do something irregular and not expressible in 
the language in making C.prototype for built-in class C a firstborn that 
may or may not be fully constructed, that has a [[Prototype]] != itself 
(of course, but different from every other instance of C), etc. This is 
a botch to fix. However:


2. We could change C.prototype to be an Object instance with the right 
[[Prototype]] and 'constructor', minimally. That's what CoffeeScript and 
the best-practice Domenic cited do and it neatly avoids any hidden 
mutable state. C.prototype is not a constructed B in the case of class C 
extends B, but that must be the case if we are to avoid any B that 
*creates* mutable state directly on the |this| being constructed.


3. We could go further and set @@toStringAtom in C.prototype to have 
value C. That lines up with 'constructor' but of course lies its head 
off since C.prototype is not actually a C instance.


My current favored answers for all constructors, built-in or not, 
phrasing the question as Should we fix/do it? 1: y, 2: y, 3: n.


If we can't break compat by making built-ins answer 3: n, then I would 
want uniformity: 1: y, 2: y, 3: y. This is where we may part company -- 
I can understand wanting to split the answer depending on legacy vs. 
non-legacy.


So first thing to try is breaking compat on the answer to 3. I will see 
about that...


/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Norbert Lindenberg

On Oct 1, 2012, at 15:53 , Brendan Eich wrote:

 2) BuiltIn.prototype has state that lets BuiltIn methods successfully 
 operate on the object, at least as long as they don't modify the state.
 
 True for ES5 objects, currently also true for ES Internationalization 
 objects. This means Intl.Collator.prototype can be used as a Collator with 
 default properties, which applications might find useful. Discussion so far 
 inconclusive.
 
 Mark has a conclusion: don't hide mutable state behind accessors in a 
 prototype. The reason is that Object.freeze can't freeze such state. Is 
 Intl.Collator.prototype's state hidden that way, or exposed to Object.freeze?

All state in Collator  Co. instances is hidden in internal properties, but we 
don't provide any means to modify the state after construction.

 3) The state mentioned in 2) is modifiable.
 
 True for some ES5 objects (Array, Date, RegExp),
 
 Don't forget Object :-P.

I'm thinking of state that goes beyond an empty object and makes a BuiltIn 
instance function as a BuiltIn instance. Object instances have no such state. 
Of course any prototype object is created extensible, so you can add properties 
that aren't relevant to its being a BuiltIn instance.

  not true for ES Internationalization objects. The discussion seems to 
 conclude that modifiable prototype objects are a bad idea.
 
 I'm not sure -- I would say the known problem is hidden (to Object.freeze) 
 mutable state, not data properties such as RegExp.lastIndex. Mark should 
 confirm.

Mutable state that can't be frozen is particularly dangerous, but there were 
also objections to having Map.prototype or Array.prototype as global storage 
bins.

 4) Object.getPrototypeOf(BuiltIn.prototype) returns BuiltIn.prototype.
 
 False for ES5 objects and ES Internationalization objects. This would lead 
 to infinite loops when looking up properties that don't exist, and we 
 probably don't want that.
 
 Yes, this makes no sense, not a goal in any scenario.
 
 5) BuiltIn.prototype instanceof BuiltIn evaluates to true.
 
 False for ES5 objects and ES Internationalization objects. The ES5 spec for 
 instanceof relies on 4).
 
 Indeed this cannot be true given that o instanceof C always gets o's 
 [[Prototype]] before matching against C.prototype -- always hops one up the 
 chain.

If 4) were true, you'd have an infinite chain, so one hop wouldn't be an issue 
at all.

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Brendan Eich

Norbert Lindenberg wrote:

On Oct 1, 2012, at 15:53 , Brendan Eich wrote:


2) BuiltIn.prototype has state that lets BuiltIn methods successfully operate 
on the object, at least as long as they don't modify the state.

True for ES5 objects, currently also true for ES Internationalization objects. 
This means Intl.Collator.prototype can be used as a Collator with default 
properties, which applications might find useful. Discussion so far 
inconclusive.

Mark has a conclusion: don't hide mutable state behind accessors in a 
prototype. The reason is that Object.freeze can't freeze such state. Is 
Intl.Collator.prototype's state hidden that way, or exposed to Object.freeze?


All state in Collator  Co. instances is hidden in internal properties, but we 
don't provide any means to modify the state after construction.


So the state is immutable after construction?


3) The state mentioned in 2) is modifiable.

True for some ES5 objects (Array, Date, RegExp),

Don't forget Object :-P.


I'm thinking of state that goes beyond an empty object and makes a BuiltIn 
instance function as a BuiltIn instance. Object instances have no such state.


Can Arrays? Remember, 'length' is observable just a data property and 
the custom [[DefineOwnProperty]] or [[Put]] hook is not state.



  Of course any prototype object is created extensible, so you can add 
properties that aren't relevant to its being a BuiltIn instance.


Indeed (see below).


  not true for ES Internationalization objects. The discussion seems to 
conclude that modifiable prototype objects are a bad idea.

I'm not sure -- I would say the known problem is hidden (to Object.freeze) 
mutable state, not data properties such as RegExp.lastIndex. Mark should 
confirm.


Mutable state that can't be frozen is particularly dangerous, but there were 
also objections to having Map.prototype or Array.prototype as global storage 
bins.


That's no more an issue than any unfrozen prototype including Object, 
which is what we're discussing (DavaView.prototype is an Object instance).


The issue is the unfreezable mutable hidden state, which makes a side 
channel.



4) Object.getPrototypeOf(BuiltIn.prototype) returns BuiltIn.prototype.

False for ES5 objects and ES Internationalization objects. This would lead to 
infinite loops when looking up properties that don't exist, and we probably 
don't want that.

Yes, this makes no sense, not a goal in any scenario.


5) BuiltIn.prototype instanceof BuiltIn evaluates to true.

False for ES5 objects and ES Internationalization objects. The ES5 spec for 
instanceof relies on 4).

Indeed this cannot be true given that o instanceof C always gets o's [[Prototype]] before 
matching against C.prototype -- always hops one up the chain.


If 4) were true, you'd have an infinite chain, so one hop wouldn't be an issue 
at all.


But 4 is false :-P. I was going in order, but if you want to make these 
independent, then ok!


/be




___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Allen Wirfs-Brock

On Oct 1, 2012, at 3:48 PM, Brendan Eich wrote:

 Allen Wirfs-Brock wrote:
 
 
 
 Let me try explaining this again,
 
 No need to rehash.
 
 Responding to my point about other legacy tag tests that are not twiddled 
 with ~ and so are possibly invalidated would be helpful. *Why* are the 
 core language names sacrosanct when tag-testing of other class names is also 
 potentially just as important, e.g., for SES?


My main concern isn't SES-like things.  It is random general use of 
Obj.proto.toString to identify instances of built-ins such as Array and 
Function.

I think we have to support reliable Obj.proto.toString-based tag-test for 
Arguments, Array, Boolean, Date, Error, Function, JSON, Math, 
Number, RegExp, and String because those specific values are explicitly 
defined in the ES5.1 specification and are universally supported by 
implementations.  Assigning one of those tags (via @@toStringTag or any other 
mechanism) may break existing code. 

The only other legacy tag tests presumably are of DOM objects (or other 
non-standard built-ins).  I don't thing we have an obligation to preserve 
legacy code with such dependencies that isn't already universally 
interoperable.  I would be more concerned about the DOM objects if there had 
been a history of consistency of tag values among implementations (but we may 
be racing the WebIDL implementation clock in this regard).  

Also as we move into a much larger space of classes and that includes the 
possibility of self-hosting libraries such as the DOM it is rapidly becoming 
impractical to guarantee the unique mapping to such toString tags to specific 
implementations of an abstraction.

So, my position is that we only guarantee the above toString tag tests that are 
carry overs from ES = 5.1and that we loudly state Obj.proto.toString can not 
be used as a reliable nominal type tag for any other objects.  We essentially 
(except for the  11 above cases) let Obj.proto.toString revert to its rightful 
place as a debugging aid.

 
 The little quicks like the ~ prefix and the exception eating are simply 
 what is necessary
 
 Not so fast there, Tex!
 
 First, *something* is necessary for preserving certain names from being 
 spoofed and invalidating a tag-test, but we should agree on the names and the 
 reason for spoof-proofing exactly and only that set of names.

Of course, there are other ways of preventing spoofing.  The key point is we 
need to avoid spoofing that interferes with legacy test of the 11 ES5  tags. 

 
 Second, eating exceptions does *not* follow from what is necessary even if 
 I agree with your set of names! Eating exceptions is bad on principle. Why do 
 you do it here? A host object might throw on attempt to get a novel property 
 name such as @@toStringTag but is that an actual concern?

Yes, eating exception is  a separable issue. But I have thought of it as a 
compatibility issue.  Obj.proto.toString never throws in ES=5.1.  Adding 
conditions where it does throw seems like a potentially breaking change.  For 
example, an self-host object inspector implementation many not currently be 
wrapping calls to Obj.proto.toString with an exception handler because it 
thinks that call never throws.

Once we get beyond using Obj.proto.toString as a nominal type tester, its 
primary use is going to be as a diagnostic/debugging aid.  From that 
perspective having the tag access throw what is likely to be an uncaught 
exception seems undesirable.  Better to just indicate in the debug text that 
an some unexpected occurred.

 
 Also, I'm assuming the ??? strings are just place-holders. True?

Sure, it could be any thing, include a description of the exception that 
occurred. 
 
  to formalize this extensibility model while still preserving the behavior 
 of existing code that depends upon object.prototype.toString as a reliable 
 mechanism to test for instances of the ES=5.1 built-ins.
 
 Adding new internal method calls with novel ids might add new exception 
 throws. That's part of the package deal.

Yes, in general I agree.  But given the primarily debugging use of 
@@toStringTag, an exception seems undesirable.  If we were talking about 
something like @@interator I would agree that eating exceptions would be highly 
undesirable.

 
 Implementors control their host objects in general and can tame any that 
 might throw on @@toStringTag [[Get]]. Suppose an implementation has a bug 
 where such a throw happens, for any reason (could be the novel symbol 
 property-name, or could be some other reason). Suppressing prevents anyone 
 (implementor, developer, us) from knowing what is going on.

But we aren't just talking about platform implementors and host objects.  This 
is now an extension point that anyone defining a set of classes might (probably 
should) use. 
 
 I'm laboring over this because in JS1 I suppressed exceptions trying toString 
 and valueOf and that bit back. [[DefaultValue]] uses ReturnIfAbrupt which 
 propagates the abrupt 

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

2012-10-01 Thread Brendan Eich

Allen Wirfs-Brock wrote:

On Oct 1, 2012, at 3:48 PM, Brendan Eich wrote:

Allen Wirfs-Brock wrote:





Let me try explaining this again,


No need to rehash.

Responding to my point about other legacy tag tests that are not 
twiddled with ~ and so are possibly invalidated would be helpful. 
*Why* are the core language names sacrosanct when tag-testing of 
other class names is also potentially just as important, e.g., for SES?



My main concern isn't SES-like things.  It is random general use of 
Obj.proto.toString to identify instances of built-ins such as Array 
and Function.


I think we have to support reliable Obj.proto.toString-based tag-test 
for Arguments,


I doubt any deployed JS code cares -- that's new in ES5. Prior to ES5, 
arguments objects seemed to be Object instances. People do not write 
ES5-only JS. Testing for arguments across pre-ES5 and ES5 engines is 
thus hard and not done in my experience.


Array, Boolean, Date, Error, Function, JSON, Math, 
Number, RegExp, and String because those specific values are 
explicitly defined in the ES5.1 specification and are universally 
supported by implementations.


This is circular, though. The spec is not the interop or backward 
compatibility requirement, it's map not terrain!


The dangerous objects outside of these may well be of more real 
compatibility importance. Suspect Mark knows all but is filtering email.


/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Norbert Lindenberg

On Oct 1, 2012, at 16:41 , Brendan Eich wrote:

 Norbert Lindenberg wrote:
 On Oct 1, 2012, at 15:53 , Brendan Eich wrote:
 
 2) BuiltIn.prototype has state that lets BuiltIn methods successfully 
 operate on the object, at least as long as they don't modify the state.
 
 True for ES5 objects, currently also true for ES Internationalization 
 objects. This means Intl.Collator.prototype can be used as a Collator with 
 default properties, which applications might find useful. Discussion so 
 far inconclusive.
 Mark has a conclusion: don't hide mutable state behind accessors in a 
 prototype. The reason is that Object.freeze can't freeze such state. Is 
 Intl.Collator.prototype's state hidden that way, or exposed to 
 Object.freeze?
 
 All state in Collator  Co. instances is hidden in internal properties, but 
 we don't provide any means to modify the state after construction.
 
 So the state is immutable after construction?

Correct.

 3) The state mentioned in 2) is modifiable.
 
 True for some ES5 objects (Array, Date, RegExp),
 Don't forget Object :-P.
 
 I'm thinking of state that goes beyond an empty object and makes a BuiltIn 
 instance function as a BuiltIn instance. Object instances have no such state.
 
 Can Arrays? Remember, 'length' is observable just a data property and the 
 custom [[DefineOwnProperty]] or [[Put]] hook is not state.

length is part of the state, but you're right, sometimes it takes more than 
state and visible methods.

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Brendan Eich

Norbert Lindenberg wrote:

  3) The state mentioned in 2) is modifiable.
  
  True for some ES5 objects (Array, Date, RegExp),

  Don't forget Object:-P.
  
  I'm thinking of state that goes beyond an empty object and makes a BuiltIn instance function as a BuiltIn instance. Object instances have no such state.
  
  Can Arrays? Remember, 'length' is observable just a data property and the custom [[DefineOwnProperty]] or [[Put]] hook is not state.


length is part of the state, but you're right, sometimes it takes more than 
state and visible methods.


To be concrete, 'length' on an Array instance can be frozen (modulo 
implementation bugs to be fixed).


The issue is really mutable state hidden from Object.freeze. Mark will 
I'm sure confirm (and I'm sorry for filling his inbox!). Array is not a 
problem in this light. Glad to hear Intl.Collator isn't either.


/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Mark S. Miller
Hi. Not filtering, just too busy to do more than skim.

On Mon, Oct 1, 2012 at 5:40 PM, Brendan Eich bren...@mozilla.org wrote:

 Norbert Lindenberg wrote:

   3) The state mentioned in 2) is modifiable.
 True for some ES5 objects (Array, Date, RegExp),

   Don't forget Object:-P.

 I'm thinking of state that goes beyond an empty object and
 makes a BuiltIn instance function as a BuiltIn instance. Object instances
 have no such state.

 Can Arrays? Remember, 'length' is observable just a data property
 and the custom [[DefineOwnProperty]] or [[Put]] hook is not state.


 length is part of the state, but you're right, sometimes it takes more
 than state and visible methods.


 To be concrete, 'length' on an Array instance can be frozen (modulo
 implementation bugs to be fixed).

 The issue is really mutable state hidden from Object.freeze. Mark will I'm
 sure confirm (and I'm sorry for filling his inbox!). Array is not a problem
 in this light. Glad to hear Intl.Collator isn't either.


The security issue is primordial state that can't be made deeply immutable
with freeze, such as ES5 Date.prototype, FF WeakMap.prototype, or the
non-standard, non-deletable RegExp statics implemented by several browsers.
Array.prototype being an array is unfortunate, but so long
as Object.freeze(Array.prototype) works correctly, it's not a security
problem.  For new buildins and classes, I agree that constructor.prototype
should be an object with the conventional class-inheritance-like wiring
(constructor.prototype.constructor === constructor,
constructor.prototype.[[Prototype]] == superconstructor.prototype). Classes
should not try to make prototypes which are prototypical instances in any
sense.

Regarding the integrity of original Object.prototype.toString.call as a
branding mechanism, I agree we need a new more general branding mechanism.
WeakMaps and Symbols both give us a place to hang this, but we need a
concrete proposal. The proposal should work both with builtins and with
classes. If a better branding proposal waits till ES7, then we need to
preserve integrity of original Object.prototype.toString.call as a branding
mechanism through ES6. If this is preserved through ES6, then it probably
becomes too entrenched to consider retiring.

Were there other questions for me that I missed?




 /be




-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Brendan Eich

Mark S. Miller wrote:
Regarding the integrity of original Object.prototype.toString.call as 
a branding mechanism, I agree we need a new more general branding 
mechanism. WeakMaps and Symbols both give us a place to hang this, but 
we need a concrete proposal. The proposal should work both with 
builtins and with classes. If a better branding proposal waits till 
ES7, then we need to preserve integrity of original 
Object.prototype.toString.call as a branding mechanism through ES6. If 
this is preserved through ES6, then it probably 
becomes too entrenched to consider retiring.


Were there other questions for me that I missed?


Yes. Should (per the latest draft, 15.2.4.2 Object.prototype.toString) 
the following names:


Arguments, Array, Boolean, Date, Error, Function, JSON, 
Math, Number, Object, RegExp, or String


and Object (per Allen here), and only these names, be prefixed with 
~ when returned via [[Get]](@@toStringTag) where @@toStringTag denotes 
a spec-internal (implementation-internal) symbol?


The idea is to uphold ES5's paragraph from Clause 15, starting

''The value of the [[Class]] internal property is defined by this 
specification for every kind of built-in object. The
value of the [[Class]] internal property of a host object may be any 
String value except one of Arguments,
Array, Boolean, Date, Error, Function, JSON, Math, 
Number, Object,

RegExp, and String.''

Step 4 uses [[NativeBrand]] in preference to @@toStringTag, which 
enables the core-language built-ins to return, e.g., Array without 
fear of ~ being prepended.


This two-level scheme seems like overkill, and the clause 15 intro 
restriction on host objects claiming, e.g., to be of Function 
[[Class]] (presumably to be updated to [[NativeBrand]]) seems 
unnecessary to me. If a host function satisfies all the observable 
requirements of a native one, why not?


I asked a question aimed more directly at you up-thread: why should 
*only* the above 12 or 13 names be subject to ~-prepending when 
returned from an object that lacks [[NativeBrand]]? Are there not host 
objects in need of protection from class-spoofing?


/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Mark S. Miller
On Mon, Oct 1, 2012 at 8:17 PM, Brendan Eich bren...@mozilla.com wrote:

 Mark S. Miller wrote:

 Regarding the integrity of original Object.prototype.toString.call as a
 branding mechanism, I agree we need a new more general branding mechanism.
 WeakMaps and Symbols both give us a place to hang this, but we need a
 concrete proposal. The proposal should work both with builtins and with
 classes. If a better branding proposal waits till ES7, then we need to
 preserve integrity of original Object.prototype.toString.call as a branding
 mechanism through ES6. If this is preserved through ES6, then it probably
 becomes too entrenched to consider retiring.

 Were there other questions for me that I missed?


 Yes. Should (per the latest draft, 15.2.4.2 Object.prototype.toString) the
 following names:


 Arguments, Array, Boolean, Date, Error, Function, JSON,
 Math, Number, Object, RegExp, or String

 and Object (per Allen here), and only these names, be prefixed with ~
 when returned via [[Get]](@@toStringTag) where @@toStringTag denotes a
 spec-internal (implementation-internal) symbol?


The ~ looks very ugly to me. As I state above, I would rather we invent a
more general branding mechanism and then stop making this requirement
on original Object.prototype.toString.call. Relaxing this requirement would
still technically be a breaking change from ES5 so we need to be cautious.
But I bet we can get away with it if we do it by ES6. By ES7 it will
probably be too late.




 The idea is to uphold ES5's paragraph from Clause 15, starting

 ''The value of the [[Class]] internal property is defined by this
 specification for every kind of built-in object. The
 value of the [[Class]] internal property of a host object may be any
 String value except one of Arguments,

 Array, Boolean, Date, Error, Function, JSON, Math, Number,
 Object,
 RegExp, and String.''

 Step 4 uses [[NativeBrand]] in preference to @@toStringTag, which enables
 the core-language built-ins to return, e.g., Array without fear of ~
 being prepended.

 This two-level scheme seems like overkill, and the clause 15 intro
 restriction on host objects claiming, e.g., to be of Function [[Class]]
 (presumably to be updated to [[NativeBrand]]) seems unnecessary to me. If a
 host function satisfies all the observable requirements of a native one,
 why not?


If a host function satisfies *all* the observable requirements of a native
one, then it is simply misclassified. It *is* a host-provided *native*
function and should have a [[Class]] of Function. (Allen, thank you for
getting us away from this awful host and native terminology!)



 I asked a question aimed more directly at you up-thread: why should *only*
 the above 12 or 13 names be subject to ~-prepending when returned from an
 object that lacks [[NativeBrand]]? Are there not host objects in need of
 protection from class-spoofing?


In the ES5 timeframe, there were hard limits on how much cleanup of host
objects we could do before finalizing the spec. Given the constraints, I
think it's miraculous that we cleaned them up as much as we did. There is
one form of spoofing protection that we did enforce by these rules for host
objects, they cannot pretend to be native objects, and no native object can
pretend to be a host object.





 /be




-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Brendan Eich

Mark S. Miller wrote:
On Mon, Oct 1, 2012 at 8:17 PM, Brendan Eich bren...@mozilla.com 
mailto:bren...@mozilla.com wrote:


Mark S. Miller wrote:

Regarding the integrity of original
Object.prototype.toString.call as a branding mechanism, I
agree we need a new more general branding mechanism. WeakMaps
and Symbols both give us a place to hang this, but we need a
concrete proposal. The proposal should work both with builtins
and with classes. If a better branding proposal waits till
ES7, then we need to preserve integrity of original
Object.prototype.toString.call as a branding mechanism through
ES6. If this is preserved through ES6, then it probably
becomes too entrenched to consider retiring.

Were there other questions for me that I missed?


Yes. Should (per the latest draft, 15.2.4.2
Object.prototype.toString) the following names:


Arguments, Array, Boolean, Date, Error, Function,
JSON, Math, Number, Object, RegExp, or String

and Object (per Allen here), and only these names, be prefixed
with ~ when returned via [[Get]](@@toStringTag) where
@@toStringTag denotes a spec-internal (implementation-internal)
symbol?


The ~ looks very ugly to me. As I state above, I would rather we 
invent a more general branding mechanism and then stop making this 
requirement on original Object.prototype.toString.call.


Agreed, let's do it.

Relaxing this requirement would still technically be a breaking change 
from ES5 so we need to be cautious. But I bet we can get away with it 
if we do it by ES6. By ES7 it will probably be too late.


I doubt it'll be too late. In part I am skeptical because I do not 
believe any engine actually prevents host objects from spoofing the 13 
class names listed above. Anyone know of an engine that does?


Words on paper still carry force but they do not necessarily have prompt 
effects, or any effects. It depends on the people reading them and 
implementing, and trying to follow the rules. Those people are much more 
likely to audit their (closed, per release, typically) set of host 
objects and fix any spoofers.



The idea is to uphold ES5's paragraph from Clause 15, starting

''The value of the [[Class]] internal property is defined by this
specification for every kind of built-in object. The
value of the [[Class]] internal property of a host object may be
any String value except one of Arguments,

Array, Boolean, Date, Error, Function, JSON, Math,
Number, Object,
RegExp, and String.''

Step 4 uses [[NativeBrand]] in preference to @@toStringTag, which
enables the core-language built-ins to return, e.g., Array
without fear of ~ being prepended.

This two-level scheme seems like overkill, and the clause 15 intro
restriction on host objects claiming, e.g., to be of Function
[[Class]] (presumably to be updated to [[NativeBrand]]) seems
unnecessary to me. If a host function satisfies all the observable
requirements of a native one, why not?


If a host function satisfies *all* the observable requirements of a 
native one, then it is simply misclassified. It *is* a host-provided 
*native* function and should have a [[Class]] of Function.


[[NativeBrand]] -- but then there's no spoofing issue.

The anti-spoofing defense in ES5 was advisory. Now we have a tiny bit of 
~-prefixing mandatory specification, but predicated on (still using 
the old terms) native vs. host object classes, the [[NativeBrand]] 
test for the former and @@toStringTag for the latter (with ~-prefixing 
for the 13 names). I think this is the wrong direction.


(Allen, thank you for getting us away from this awful host and 
native terminology!)


Are ordinary and exotic any better or worse? A rose by any name 
would smell as sweet, a host-rose as sour.


But the @@toStringTag idea is a win. Why not use it uniformly, tag all 
the natives and use advisory language to require that only 
implementation(s) of objects that satisfy, e.g., the function contract, 
can use Function?



I asked a question aimed more directly at you up-thread: why
should *only* the above 12 or 13 names be subject to
~-prepending when returned from an object that lacks
[[NativeBrand]]? Are there not host objects in need of protection
from class-spoofing?


In the ES5 timeframe, there were hard limits on how much cleanup of 
host objects we could do before finalizing the spec. Given the 
constraints, I think it's miraculous that we cleaned them up as much 
as we did. There is one form of spoofing protection that we did 
enforce by these rules for host objects, they cannot pretend to be 
native objects, and no native object can pretend to be a host object.


You guys did make some good moves, but that was then. I would like us to 
go farther, but not in the mandatory-classname-rewriting-list direction.


And I'm really asking whether, should we 

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

2012-10-01 Thread Mark S. Miller
On Mon, Oct 1, 2012 at 9:02 PM, Brendan Eich bren...@mozilla.com wrote:

 Mark S. Miller wrote:

[...]

  Relaxing this requirement would still technically be a breaking change
 from ES5 so we need to be cautious. But I bet we can get away with it if we
 do it by ES6. By ES7 it will probably be too late.


 I doubt it'll be too late. In part I am skeptical because I do not believe
 any engine actually prevents host objects from spoofing the 13 class names
 listed above. Anyone know of an engine that does?


host objects are part of the TCB. There's no enforcement needed; an engine
running a malicious host object is already toast. What's required is that
host objects not do this, not that engines prevent them from doing so.




 Words on paper still carry force but they do not necessarily have prompt
 effects, or any effects. It depends on the people reading them and
 implementing, and trying to follow the rules. Those people are much more
 likely to audit their (closed, per release, typically) set of host objects
 and fix any spoofers.


I think we're agreeing but for one thing. The force of a normative
specification is that violations can be added to test262, so that they
stand out like a sore thumb, putting pressure on the violator to fix it. We
already did this successfully with one host object violation.




 If a host function satisfies *all* the observable requirements of a
 native one, then it is simply misclassified. It *is* a host-provided
 *native* function and should have a [[Class]] of Function.


 [[NativeBrand]] -- but then there's no spoofing issue.

 The anti-spoofing defense in ES5 was advisory.


It was most certainly not. It was and is normative.



 Now we have a tiny bit of ~-prefixing mandatory specification, but
 predicated on (still using the old terms) native vs. host object
 classes, the [[NativeBrand]] test for the former and @@toStringTag for the
 latter (with ~-prefixing for the 13 names). I think this is the wrong
 direction.


Agreed. I think the ~ thing is terrible.





  (Allen, thank you for getting us away from this awful host and native
 terminology!)


 Are ordinary and exotic any better or worse? A rose by any name would
 smell as sweet, a host-rose as sour.


It's hard to do worse than native and host, but I don't like ordinary
and exotic either. Time for more bikeshedding ;).



 But the @@toStringTag idea is a win. Why not use it uniformly, tag all the
 natives and use advisory language to require that only implementation(s) of
 objects that satisfy, e.g., the function contract, can use Function?


Again, if it satisfies the function contract, then it *is* a function, so
even by ES5's normative requirements, it should have [[Class]] Function.

I don't understand the contract-obeying spoofing scenario you have in mind.





  I asked a question aimed more directly at you up-thread: why
 should *only* the above 12 or 13 names be subject to
 ~-prepending when returned from an object that lacks
 [[NativeBrand]]? Are there not host objects in need of protection
 from class-spoofing?


 In the ES5 timeframe, there were hard limits on how much cleanup of host
 objects we could do before finalizing the spec. Given the constraints, I
 think it's miraculous that we cleaned them up as much as we did. There is
 one form of spoofing protection that we did enforce by these rules for host
 objects, they cannot pretend to be native objects, and no native object can
 pretend to be a host object.


 You guys did make some good moves, but that was then. I would like us to
 go farther, but not in the mandatory-classname-rewriting-**list direction.


Agreed.



 And I'm really asking whether, should we fail to agree on a less mandatory
 and hacky solution than ~-prefixing, we will end up needing to enlarge
 the blacklist from 13 names to more.


I don't think so but I'm not sure. Do we have a consolidated list of the
new builtin contracts, so that we can look at these on a case by case basis?



 Don't you have to use tag-testing on DOM objects in SES?


Not when Caja is used together with SES. With Caja+SES, only Domado ever
gets direct access to a DOM object. All other code only gets Domado-created
wrappers. Domado itself is careful never to confuse itself about when it is
dealing with a DOM object vs something else. To pull this off, Domado does
brand its own wrappers so it can recognize them when they're presented as
arguments.

To date, the only use of SES without the rest of Caja has been outside the
browser, where there are no DOM objects.




 /be




-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Allen Wirfs-Brock

On Oct 1, 2012, at 9:02 PM, Brendan Eich wrote:

 Mark S. Miller wrote:
 On Mon, Oct 1, 2012 at 8:17 PM, Brendan Eich bren...@mozilla.com 
 mailto:bren...@mozilla.com wrote:
 
Mark S. Miller wrote:
 
Regarding the integrity of original
Object.prototype.toString.call as a branding mechanism, I
agree we need a new more general branding mechanism. WeakMaps
and Symbols both give us a place to hang this, but we need a
concrete proposal. The proposal should work both with builtins
and with classes. If a better branding proposal waits till
ES7, then we need to preserve integrity of original
Object.prototype.toString.call as a branding mechanism through
ES6. If this is preserved through ES6, then it probably
becomes too entrenched to consider retiring.
 
Were there other questions for me that I missed?
 
 
Yes. Should (per the latest draft, 15.2.4.2
Object.prototype.toString) the following names:
 
 
Arguments, Array, Boolean, Date, Error, Function,
JSON, Math, Number, Object, RegExp, or String
 
and Object (per Allen here), and only these names, be prefixed
with ~ when returned via [[Get]](@@toStringTag) where
@@toStringTag denotes a spec-internal (implementation-internal)
symbol?
 
 
 The ~ looks very ugly to me. As I state above, I would rather we invent a 
 more general branding mechanism and then stop making this requirement on 
 original Object.prototype.toString.call.
 
 Agreed, let's do it.
 
 Relaxing this requirement would still technically be a breaking change from 
 ES5 so we need to be cautious. But I bet we can get away with it if we do it 
 by ES6. By ES7 it will probably be too late.
 
 I doubt it'll be too late. In part I am skeptical because I do not believe 
 any engine actually prevents host objects from spoofing the 13 class names 
 listed above. Anyone know of an engine that does?
 
 Words on paper still carry force but they do not necessarily have prompt 
 effects, or any effects. It depends on the people reading them and 
 implementing, and trying to follow the rules. Those people are much more 
 likely to audit their (closed, per release, typically) set of host objects 
 and fix any spoofers.


The point of the  the the spoofing protection isn't about existing or even 
future host objects.   It about everyday code that user could write if me 
make Obj.proto.toString extensible via @@toStringTag.

I think using toString as a nominal type test is a crock that we should 
perpetuate.  But we know that code exists that uses it that way for the tags 
that are defined by ES=5.1. If we think it is ok to allow future ES programmer 
to invalidate such existing code by using strings like Function and Array 
as @@toStringTag values, then we don't need to do any spoof protection such as 
the ~ prefix. 

 ...
 But the @@toStringTag idea is a win. Why not use it uniformly, tag all the 
 natives and use advisory language to require that only implementation(s) of 
 objects that satisfy, e.g., the function contract, can use Function?
 

Because such advisory language would have no practical effect on developer 
writing ES code.  Most would probably not even be away of such a restriction if 
there isn't some enforcement.

We can try to tell ES implementors that they must do certain things in order to 
be in conformance but that really doesn't work for code written by users of the 
language. 

...

Allen
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Brendan Eich

Mark S. Miller wrote:
On Mon, Oct 1, 2012 at 9:02 PM, Brendan Eich bren...@mozilla.com 
mailto:bren...@mozilla.com wrote:


Mark S. Miller wrote:

[...]

Relaxing this requirement would still technically be a
breaking change from ES5 so we need to be cautious. But I bet
we can get away with it if we do it by ES6. By ES7 it will
probably be too late.


I doubt it'll be too late. In part I am skeptical because I do not
believe any engine actually prevents host objects from spoofing
the 13 class names listed above. Anyone know of an engine that does?


host objects are part of the TCB. There's no enforcement needed; an 
engine running a malicious host object is already toast. What's 
required is that host objects not do this, not that engines prevent 
them from doing so.


Agreed, but that's not consistent with the ~-prefixing.


Words on paper still carry force but they do not necessarily have
prompt effects, or any effects. It depends on the people reading
them and implementing, and trying to follow the rules. Those
people are much more likely to audit their (closed, per release,
typically) set of host objects and fix any spoofers.


I think we're agreeing but for one thing. The force of a normative 
specification is that violations can be added to test262, so that they 
stand out like a sore thumb, putting pressure on the violator to fix 
it. We already did this successfully with one host object violation.


Agreed again.


If a host function satisfies *all* the observable requirements
of a native one, then it is simply misclassified. It *is* a
host-provided *native* function and should have a [[Class]] of
Function.


[[NativeBrand]] -- but then there's no spoofing issue.

The anti-spoofing defense in ES5 was advisory.


It was most certainly not. It was and is normative.


Apologies, I misspoke -- advisory was my attempt to say that prose in 
Clause 15 intro asserted something to secure by auditing -- not by 
~-prefixing!


Perhaps normative-audit-based vs. normative-runtime-check-based? Argh.


Now we have a tiny bit of ~-prefixing mandatory specification,
but predicated on (still using the old terms) native vs. host
object classes, the [[NativeBrand]] test for the former and
@@toStringTag for the latter (with ~-prefixing for the 13
names). I think this is the wrong direction.


Agreed. I think the ~ thing is terrible.


Good to discuss it, then.


(Allen, thank you for getting us away from this awful host
and native terminology!)


Are ordinary and exotic any better or worse? A rose by any
name would smell as sweet, a host-rose as sour.


It's hard to do worse than native and host, but I don't like 
ordinary and exotic either. Time for more bikeshedding ;).


Best if we can get the differences down to what a Proxy can do!


But the @@toStringTag idea is a win. Why not use it uniformly, tag
all the natives and use advisory language to require that only
implementation(s) of objects that satisfy, e.g., the function
contract, can use Function?


Again, if it satisfies the function contract, then it *is* a function, 
so even by ES5's normative requirements, it should have [[Class]] 
Function.


I don't understand the contract-obeying spoofing scenario you have in 
mind.


See the latest draft: 15.2.4.2 Object.prototype.toString does that 
~-prefixing only for a host object trying to tag itself as a 
Function. If such a host object existed (let's say the implementation 
had good reason not to use a native function, perhaps due to some legacy 
DLL extension mechanism compatibility) and the host object indeed 
satisfied the function object contract, ES6 as drafted would prefix a 
big ugly ~ on Function!


Seems like a problem, in theory. Of course I am contriving the host 
object emulating a native function case -- or am I? IE with COM? Not so 
sure



And I'm really asking whether, should we fail to agree on a less
mandatory and hacky solution than ~-prefixing, we will end up
needing to enlarge the blacklist from 13 names to more.


I don't think so but I'm not sure. Do we have a consolidated list of 
the new builtin contracts, so that we can look at these on a case by 
case basis?


We have a spec, it's about as good as one can hope for right now, and 
getting better for ES6.


Did you have a more detailed or differently-formulated spec than ES6 
draft, clauses 13 and 15, select parts?



Don't you have to use tag-testing on DOM objects in SES?


Not when Caja is used together with SES. With Caja+SES, only Domado 
ever gets direct access to a DOM object. All other code only gets 
Domado-created wrappers. Domado itself is careful never to confuse 
itself about when it is dealing with a DOM object vs something else. 
To pull this off, Domado does brand its own wrappers so it can 
recognize them when they're presented as 

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

2012-10-01 Thread Brendan Eich

Allen Wirfs-Brock wrote:

We can try to tell ES implementors that they must do certain things in order to 
be in conformance but that really doesn't work for code written by users of the 
language.


You're right, we'd be letting usercode, not just some (benign or malign, 
but if malign then game over already) host object, spoof a core language 
built-in.


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.


/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-10-01 Thread Brendan Eich

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
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-09-30 Thread Brendan Eich

Norbert Lindenberg wrote:

Last week TC 39 approved a standard defining three new built-in constructors whose 
instances and prototype objects all have [[Class]] Object. Also, the 
prototype objects are not constructed by their respective constructors, but initialized 
by them, e.g., as Intl.Collator.call({}).

Are you suggesting they should have Collator, NumberFormat, and 
DateTimeFormat, respectively, and the prototypes be specified as being constructed by their 
constructors?


All else equal, yes (sorry for not flagging these).

Any non-equal elses in sight?

/be


Thanks,
Norbert


On Sep 29, 2012, at 22:24 , Brendan Eich wrote:


Mark S. Miller wrote:

Security aside, given maximin

class Foo

what do you suggest Foo.prototype be?

If classes are sugar for constructor functions, an Object instance, just as 
you'd get for

  function Foo(){}
  Foo.prototype

There has always been an unsightly difference between built-in constructors and 
user-defined ones. Whether or how we reduce that gulf is separable from what 
the [[NativeBrand]] or [[Class]] of a built-in's prototype should be.

When self-hosting built-ins, this matters. Suppose [[NativeBrand]] could be a 
symbol private to the built-ins. That would allow the engine to set up 
bespoke-looking prototypes as it needs to for ES1-5 compatibility. But should 
user-defined classes have access to this symbol?

/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-09-30 Thread Brendan Eich

Mark S. Miller wrote:
On Sat, Sep 29, 2012 at 10:21 PM, Mark S. Miller erig...@google.com 
mailto:erig...@google.com wrote:



I agree that the only security issue is avoiding the
communications channel.

Security aside, given maximin

class Foo

what do you suggest Foo.prototype be?


That was too vague. Reformulating.

Private properties, i.e., properties named by symbols, are the class 
analog to the internal properties of the built ins. The current 
[[Class]] tests in ES5 are there essentially to ensure that these 
internal properties exist and satisfy whatever invariant is assumed. 
In maximin classes, we don't expand methods with an analog of that 
[[Class]] check. Rather, the presence of these private symbol-named 
properties implicitly provides the branding. Say class Foo uses symbol 
@s to name a private instance property of instances of Foo, and that 
method bar() of Foo accesses this @s property, failing if the object 
doesn't have an @s. Clearly, bar() should fail on Foo.prototype just 
as it should fail on any non-instance of Foo. This is already implied 
by the mechanisms proposed for installing private instance variables.


Yup, and I dig it (Jason Orendorff many years ago suggested that Date 
should not have a [[Class]] check, rather simply use private-named 
properties which might even be inherited).


So is the only issue here that @@toStringTag is not set to Foo, as 
Yusuke just suggested?


/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-09-30 Thread Brendan Eich
I hadn't reviewed the 9-27 draft's 15.2.4.2 Object.prototype.toString () 
yet. It seems to suppress exceptions, which is bad (step 6(c)(ii)). The 
...(iv) substitution of ??? for must be a placeholder but why not 
throw there (in the case where @@toStringTag's value is not of String type)?


The main thing I missed there is the prefixing of ~ on any tag naming 
a core language built-in constructor. What's this for? Why not for DOM 
built-ins too?


/be

Yusuke Suzuki wrote:


Mark S. Miller wrote:

Security aside, given maximin

class Foo

what do you suggest Foo.prototype be?


I suggest adding @@toStringTag:Foo property to Foo.prototype when 
`class Foo` is executed.


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-09-30 Thread Rick Waldron



On Sunday, September 30, 2012 at 12:04 AM, Brendan Eich wrote:

 Rick Waldron wrote:
  On Sat, Sep 29, 2012 at 6:19 PM, Brendan Eich bren...@mozilla.org 
  mailto:bren...@mozilla.org wrote:
  
  Allen Wirfs-Brock wrote:
  
  My intention, subject to feedback here and from TC39, is to
  follow the pattern I used for Map as much as possible.
  However, TypedArray object are all ready implemented by all
  major browsers to that may limit how we apply it to them.
  
  
  Implementations differ:
  
  javascript:alert(Object.prototype.toString.call(Uint8Array.prototype).slice(8,-1))
  
  in Opera says Uint8Array, while in Firefox and Safari it says
  Uint8ArrayPrototype. Chrome says Object. I can't test IE here.
  
  
  How common is that?
 
 Which that?
Using the prototype object here:

  Object.prototype.toString.call(Uint8Array.prototype).slice(8,-1))

But it's really usecase dependent, sorry for the noise
 
 
  Generally the [[Class]] (NativeBrand?) is derived via
  
  Object.prototype.toString.call(Uint8Array).slice(8,-1)
  
  (sans .prototype)
 
 s/derived/disclosed/
 
 I'm saying typed arrays from khronos are underspecified, and 
 implementations vary. Something to fix in ES6.
 
 


Got it, this answers all of my questions so far. Thanks
 
 /be 

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-09-30 Thread Brendan Eich

Brendan Eich wrote:
The main thing I missed there is the prefixing of ~ on any tag 
naming a core language built-in constructor. What's this for? Why not 
for DOM built-ins too?


This step:

v. If tag is any of Arguments, Array, Boolean, Date, Error, 
Function, JSON, Math, Number, Object, RegExp, or String 
then let tag be the string value ~ concatenated with the current value 
of tag.


Also: why no Error subclasses, e.g. SyntaxError?

/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-09-30 Thread Brendan Eich

Rick Waldron wrote:

Using the prototype object here:


Object.prototype.toString.call(Uint8Array.prototype).slice(8,-1))


But it's really usecase dependent, sorry for the noise


It's a who-cares for sure -- typed arrays are rolling, even in IE10 
(could someone please test the above there). But implementors if not 
users, and of course the spec, must care.


js var list = [Array, Boolean, Date, Error, Function, JSON, Math, 
Number, Object, RegExp, String]
js for (cls of list) if ('prototype' in cls) print(cls.name, 
cls.prototype.valueOf())

Array
Boolean false
Date NaN
Error Error
Function function () {
}
Number 0
Object [object Object]
RegExp /(?:)/
String

If the way to reconcile things is to make it unobservable whether 
C.prototype is a firstborn instance of C (possibly degenerate/useless) 
or an Object with @@toStringTag and any other such symbol-named 
decorations to satisfy observable equivalence, then we should do so for 
new built-ins too, including the typed array constructors folded into 
binary data.


/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-09-30 Thread Allen Wirfs-Brock

On Sep 29, 2012, at 11:11 PM, Brendan Eich wrote:

 Mark S. Miller wrote:
 On Sat, Sep 29, 2012 at 10:21 PM, Mark S. Miller erig...@google.com 
 mailto:erig...@google.com wrote:
 
 
I agree that the only security issue is avoiding the
communications channel.
 
Security aside, given maximin
 
class Foo
 
what do you suggest Foo.prototype be?
 
 
 That was too vague. Reformulating.
 
 Private properties, i.e., properties named by symbols, are the class analog 
 to the internal properties of the built ins. The current [[Class]] tests in 
 ES5 are there essentially to ensure that these internal properties exist and 
 satisfy whatever invariant is assumed. In maximin classes, we don't expand 
 methods with an analog of that [[Class]] check. Rather, the presence of 
 these private symbol-named properties implicitly provides the branding. Say 
 class Foo uses symbol @s to name a private instance property of instances of 
 Foo, and that method bar() of Foo accesses this @s property, failing if the 
 object doesn't have an @s. Clearly, bar() should fail on Foo.prototype just 
 as it should fail on any non-instance of Foo. This is already implied by the 
 mechanisms proposed for installing private instance variables.
 
 Yup, and I dig it (Jason Orendorff many years ago suggested that Date should 
 not have a [[Class]] check, rather simply use private-named properties which 
 might even be inherited).
 

Just so everybody is on the same page here, @@bar  is an internal convention 
I'm experimenting with in the spec. draft for referring to Symbol values that 
defined in the specification and known to implementation.  So, @@toStringTag is 
a reference to a symbol that user code would generally reference as 
@toStringTag.  This symbol is used as a property key whose value is used to 
supply the tag value that Object.prototype.toString inserts into: [Object 
tag].  See 15.2.4.2 in the lasted spec. draft.  The @@toStringTag property 
is kind of like the internal [[Class]] property in that it is used to 
parameterize the output of Object.prototype.toString.  It is different in that 
it is can be supplied by user code for the objects they define.  It is 
different in that its value is not guaranteed to be unique or non-forgegable. 
You can't use Object.prototype.toString as a reliable nominal type tag for new 
built-ins or user defined objects.  Instead use a closely head private symb
 ol.  The proposed definition of Object.prototype.toString preserves the 
ability to use it to do nominal type testing of the ES=5.1 built-ins so 
existing code should work, as is. 

 So is the only issue here that @@toStringTag is not set to Foo, as Yusuke 
 just suggested?

As currently specified, class definitions do not  automatically define a 
@@toStringTag property on the prototype object.   It is up to the developer of 
a class to decide to provide it.  If none is provided it is obtain by 
inheritance up the prototype chain and would typically have the value Object. 
 Note that not all class definitions include an identifier binding that names 
the class.  

Allen
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-09-30 Thread Allen Wirfs-Brock

On Sep 30, 2012, at 9:47 AM, Brendan Eich wrote:

 Brendan Eich wrote:
 The main thing I missed there is the prefixing of ~ on any tag naming a 
 core language built-in constructor. What's this for? Why not for DOM 
 built-ins too?
 
 This step:
 
 v. If tag is any of Arguments, Array, Boolean, Date, Error, 
 Function, JSON, Math, Number, Object, RegExp, or String then 
 let tag be the string value ~ concatenated with the current value of tag.
 
 Also: why no Error subclasses, e.g. SyntaxError?
 

To further explain the workings of the proposed revisions to 
Object.prototype.toString

If the this value is undefined, return [object Undefined].
If the this value is null, return [object Null].
Let O be the result of calling ToObject passing the this value as the 
argument.
If O has a [[NativeBrand]] internal property, let tag be the 
corresponding value from Table 27.
Else 
Let hasTag be the result of calling the [[HasProperty]] internal method 
of O with argument @@toStringTag.
If hasTag is false, let tag be Object.
Else, 
Let tag be the result of calling the [[Get]] internal method of O with 
argument @@toStringTag.
If tag is an abrupt completion, let tag be NormalCompletion(???).
Let tag be tag.[[value]].
If Type(tag) is not String, let tag be ???.
If tag is any of Arguments, Array, Boolean, Date, Error, 
Function, JSON, Math, Number, Object, RegExp, or String then let 
tag be the string value ~ concatenated with the current value of tag.
Return the String value that is the result of concatenating the three 
Strings [object , tag, and ].\

Lines 1-3 are exactly like ES5.1

Line 4 looks for well known kinds objects that are a [[Class]] internal 
property defined by ES=5.1.  They are the instances of the Math and JSON 
objects, argument objects and instances of Function, Array, String, Number, 
Boolean, Date, RegExp, and Error.  These are the only objects that are 
specified as having a [[NativeBrand]] internal method. The set isn't 
extensible. The values from the table are the [[Class]] values defined in 
ES5.1.  Note that in ES=5.1 all of the nativeError objects (TypeError, etc.) 
have the [[Class]] value Error

Line 5 and its sub-lines takes care of all other objects.
Line 5.a first looks to see if the object has @@toStringTag property, if not 
Object is used as the tag value and that's the end of the story.

Line 5.c.i retrieves the value of the @@toStringTag.  Note that this property 
could be a get accessor that could throw an exception.  In ES=5.1 
Object.prototype.toString never throws, so throwing would be an incompatible 
change.  Instead of throwin g line 5.c.ii inserts ??? as the tag value as an 
indicator that the name of the object class could no be determined.  It also 
does this if the value returned from [[Get]] of @@toStringTag is not a string.

Line 5.c.v is dealing with the ES5 requirement that host objects not reuse 
the listed [[Class]] values for anything other than the specified built-ins. 
This version of toStrimg extends the spirit to that restriction to all user or 
implementation defined tag values.  It does this by prepending a ~ in front 
of those values if they appear as a tag value.  Note that ES5.1 includes 
Object in this list so I also included it. But, I actually think it probably 
should be in the censored list.

WRT, DOM and other host objects.  The intent is that just like user code, 
they would use @@toStringTag extension point to parameterize toString rather 
than whatever implementation dependent [[Class]] extension mechanism they are 
currently working. 

Allen

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-09-29 Thread Yusuke Suzuki
Thanks for your reply.

Why did I do this?  Because, we are defining a significant number new
 built-in classes and it is going to be increasingly hard to define
 meaningful instance state for all such prototypes.  It is also arguably
 undesirable for most of these prototypes.  Does any really think it is a
 good idea for Map.prototype to be globally available storage bin into which
 anybody can store and retrieve key/value pairs?  Finally, note that the
 prototype objects created by ES6 class declarations typically are not valid
 instances of the class.  Programmers would have to go out of their way to
 initialize them with per instance state and there is really no good reason
 why somebody would do that.


Agreed.

I think it is time to recognize that the built-in ES constructors have
 always presented  a class-like structure where it really is unnecessary and
 even arguably undesirable for their associated prototype objects to also
 act as instance objects.  It's time to abandon that precedent and starting
 with the new ES6 built-ins to specify prototypes simply as objects that are
 containers of the methods shared by instances. In general, they should not
 be usable as instance objects.


Current Map constructor allows `class DerivedMap extends Map { }` and it is
very nice for ECMAScripters.
So I have an another question. Do you have a plan to change prototype of
ArrayBuffer and other objects to new style prototype, constructor of them
to new style like a Map constructor, and Class check(such as [[Class]] is
DataView) to internal property check(such as
object.[[HasProperty]](DataView)) ?
Probably because at least ArrayBuffer has no internal specialized method, I
think transforming to subclassable constructor is easy.

Regards,
Yusuke Suzuki

On Sun, Sep 30, 2012 at 6:55 AM, Allen Wirfs-Brock al...@wirfs-brock.comwrote:

 As I noted in another thread, the binary data material is very preliminary
 and and you shouldn't read too much significance into things like this
 relating to that material.

 However, there is a bigger issue here.  You could have asked a similar
  question about Map.prototype.  Why isn't Map.prototype a Map instances? Is
 this a bug or an intentional design decision?

 Historically, the prototype objects associated with the 9 named built-in
 constructors were all defined to be instances of those constructors.  For
 example, Boolean.prototype is a Boolean instance whose value is false.

 In writing the specification for Map, I intentionally deviated from that
 pattern.  I did not specify that Map.prototype is a Map instance.  While it
 has the methods that are applicable to Map instances it does not the
 internal state that is necessary for those methods to actually work.  For
 example, if you try to store a value into Map.prototype by calling its set
 method, you will get a TypeErrior according to the specification.
 May.prototype can not be used as a map object.

 Why did I do this?  Because, we are defining a significant number new
 built-in classes and it is going to be increasingly hard to define
 meaningful instance state for all such prototypes.  It is also arguably
 undesirable for most of these prototypes.  Does any really think it is a
 good idea for Map.prototype to be globally available storage bin into which
 anybody can store and retrieve key/value pairs?  Finally, note that the
 prototype objects created by ES6 class declarations typically are not valid
 instances of the class.  Programmers would have to go out of their way to
 initialize them with per instance state and there is really no good reason
 why somebody would do that.

 I think it is time to recognize that the built-in ES constructors have
 always presented  a class-like structure where it really is unnecessary and
 even arguably undesirable for their associated prototype objects to also
 act as instance objects.  It's time to abandon that precedent and starting
 with the new ES6 built-ins to specify prototypes simply as objects that are
 containers of the methods shared by instances. In general, they should not
 be usable as instance objects.

 Allen



 On Sep 29, 2012, at 2:04 PM, Yusuke Suzuki wrote:

  I've pass through ES6 rev10 draft and found that DataView.prototype
 object [[Class]] isn't DataView.
  Why is it? I think allowing DataView(null, 0, 0) and using it as
 DataView.prototype is better.
 
  --
  Regards,
  Yusuke Suzuki
  ___
  es-discuss mailing list
  es-discuss@mozilla.org
  https://mail.mozilla.org/listinfo/es-discuss


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-09-29 Thread Axel Rauschmayer
 I think it is time to recognize that the built-in ES constructors have always 
 presented  a class-like structure where it really is unnecessary and even 
 arguably undesirable for their associated prototype objects to also act as 
 instance objects.  It's time to abandon that precedent and starting with the 
 new ES6 built-ins to specify prototypes simply as objects that are containers 
 of the methods shared by instances. In general, they should not be usable as 
 instance objects.


+1

If one doesn’t explicitly look at these things, one will never find out about 
them. It mostly matters for String.prototype.match if the argument is 
RegExp.prototype and for Array.isArray if the argument Array.prototype. But how 
often does that happen?

Axel

-- 
Dr. Axel Rauschmayer
a...@rauschma.de

home: rauschma.de
twitter: twitter.com/rauschma
blog: 2ality.com

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-09-29 Thread Allen Wirfs-Brock

On Sep 29, 2012, at 4:20 PM, Yusuke Suzuki wrote:

 Thanks for your reply.
 
 Why did I do this?  Because, we are defining a significant number new 
 built-in classes and it is going to be increasingly hard to define 
 meaningful instance state for all such prototypes.  It is also arguably 
 undesirable for most of these prototypes.  Does any really think it is a good 
 idea for Map.prototype to be globally available storage bin into which 
 anybody can store and retrieve key/value pairs?  Finally, note that the 
 prototype objects created by ES6 class declarations typically are not valid 
 instances of the class.  Programmers would have to go out of their way to 
 initialize them with per instance state and there is really no good reason 
 why somebody would do that.
  
 Agreed.
 
 I think it is time to recognize that the built-in ES constructors have always 
 presented  a class-like structure where it really is unnecessary and even 
 arguably undesirable for their associated prototype objects to also act as 
 instance objects.  It's time to abandon that precedent and starting with the 
 new ES6 built-ins to specify prototypes simply as objects that are containers 
 of the methods shared by instances. In general, they should not be usable as 
 instance objects.
  
 Current Map constructor allows `class DerivedMap extends Map { }` and it is 
 very nice for ECMAScripters.
 So I have an another question. Do you have a plan to change prototype of 
 ArrayBuffer and other objects to new style prototype, constructor of them to 
 new style like a Map constructor, and Class check(such as [[Class]] is 
 DataView) to internal property check(such as 
 object.[[HasProperty]](DataView)) ?
 Probably because at least ArrayBuffer has no internal specialized method, I 
 think transforming to subclassable constructor is easy.

My intention, subject to feedback here and from TC39,  is to follow the pattern 
I used for Map as much as possible.  However, TypedArray object are all ready 
implemented by all major browsers to that may limit how we apply it to them.

Allen___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-09-29 Thread Brendan Eich

Allen Wirfs-Brock wrote:

However, there is a bigger issue here.  You could have asked a similar  
question about Map.prototype.  Why isn't Map.prototype a Map instances? Is this 
a bug or an intentional design decision?

Historically, the prototype objects associated with the 9 named built-in 
constructors were all defined to be instances of those constructors.  For 
example, Boolean.prototype is a Boolean instance whose value is false.

In writing the specification for Map, I intentionally deviated from that 
pattern.


Failing to consult with implementors will just make editing churn. I 
don't remember much discussion on this change, if any -- we did talk 
about the general problem of prototype objects being firstborns of their 
class, and how this makes them sometimes not just basis cases but 
degenerate cases.


However, Map is prototyped in SpiderMonkey and V8. In SpiderMonkey, the 
prototype is a Map, not an Object:


js Object.prototype.toString.call(Map.prototype).slice(8, -1)
Map

but you can't get, has, set, size, or iterate Map.prototype:

js Map.prototype.get('x')
typein:2:0 TypeError: get method called on incompatible Map
js Map.prototype.has('x')
typein:3:0 TypeError: has method called on incompatible Map
js Map.prototype.set('x', 42)
typein:4:0 TypeError: set method called on incompatible Map
js Map.prototype.size()
typein:5:0 TypeError: size method called on incompatible Map
js for (var [k, v] of Map.prototype) ;
typein:6:13 TypeError: iterator method called on incompatible Map

The error message is suboptimal but what's going on here is that 
Map.prototype has the SpiderMonkey equivalent of [[Class]] == Map (or 
the ES6 equivalent). This is important since all the builtins in ES3 + 
Reality (including RegExp; ES3 deviated there) make the prototype for 
built-in class C be of class C.


Your change requires implementations to provide a different built-in 
class (constructor/prototype) initialization path. That's not desirable 
_per se_. Neither IMHO is the user-facing semantic split among old and 
new constructors.


There are two separate issues here:

1. Should Map.prototype be an instance (firstborn for its realm) of 
class Map?


2. Should Map.prototype be a key/value store that can be used or abused 
as any other Map could be?


We should not mix these up. SpiderMonkey (and possibly V8, I haven't 
tested) says yes to 1 and no to 2.



   I did not specify that Map.prototype is a Map instance.  While it has the 
methods that are applicable to Map instances it does not the internal state 
that is necessary for those methods to actually work.  For example, if you try 
to store a value into Map.prototype by calling its set method, you will get a 
TypeErrior according to the specification. May.prototype can not be used as a 
map object.


That doesn't mean Map.prototype should not be classified as a Map per 1 
above.



Why did I do this?  Because, we are defining a significant number new built-in 
classes and it is going to be increasingly hard to define meaningful instance 
state for all such prototypes.


Not so, as shown above. It's trivial in SpiderMonkey to give the 
prototype no instance state and check for that. Alternative 
implementation techniques are feasible with different trade-offs.


Cc'ing implementors.

/be

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-09-29 Thread Brendan Eich

Allen Wirfs-Brock wrote:
My intention, subject to feedback here and from TC39,  is to follow 
the pattern I used for Map as much as possible.  However, TypedArray 
object are all ready implemented by all major browsers to that may 
limit how we apply it to them.


Implementations differ:

javascript:alert(Object.prototype.toString.call(Uint8Array.prototype).slice(8,-1))

in Opera says Uint8Array, while in Firefox and Safari it says 
Uint8ArrayPrototype. Chrome says Object. I can't test IE here.


The typed array 
(http://www.khronos.org/registry/typedarray/specs/latest/) does not specify.


/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-09-29 Thread Rick Waldron
On Sat, Sep 29, 2012 at 5:17 PM, Brendan Eich bren...@mozilla.org wrote:

 Allen Wirfs-Brock wrote:

 However, there is a bigger issue here.  You could have asked a similar
  question about Map.prototype.  Why isn't Map.prototype a Map instances? Is
 this a bug or an intentional design decision?

 Historically, the prototype objects associated with the 9 named built-in
 constructors were all defined to be instances of those constructors.  For
 example, Boolean.prototype is a Boolean instance whose value is false.

 In writing the specification for Map, I intentionally deviated from that
 pattern.


 Failing to consult with implementors will just make editing churn. I don't
 remember much discussion on this change, if any -- we did talk about the
 general problem of prototype objects being firstborns of their class, and
 how this makes them sometimes not just basis cases but degenerate cases.

 However, Map is prototyped in SpiderMonkey and V8. In SpiderMonkey, the
 prototype is a Map, not an Object:

 js Object.prototype.toString.**call(Map.prototype).slice(8, -1)
 Map


This should be considered a _must_have_. If the result were object, only
confusion would follow.



 but you can't get, has, set, size, or iterate Map.prototype:

 js Map.prototype.get('x')
 typein:2:0 TypeError: get method called on incompatible Map
 js Map.prototype.has('x')
 typein:3:0 TypeError: has method called on incompatible Map
 js Map.prototype.set('x', 42)
 typein:4:0 TypeError: set method called on incompatible Map
 js Map.prototype.size()
 typein:5:0 TypeError: size method called on incompatible Map
 js for (var [k, v] of Map.prototype) ;
 typein:6:13 TypeError: iterator method called on incompatible Map

 The error message is suboptimal but what's going on here is that
 Map.prototype has the SpiderMonkey equivalent of [[Class]] == Map (or the
 ES6 equivalent). This is important since all the builtins in ES3 + Reality
 (including RegExp; ES3 deviated there) make the prototype for built-in
 class C be of class C.


Subjectively, the examples here are exactly how I would expect (hope?) this
to behave, as the existing behaviour:

 Array.prototype.push(1)
1
 Array.prototype
[ 1 ]


...Has always been seemed strange ;)








 Your change requires implementations to provide a different built-in class
 (constructor/prototype) initialization path. That's not desirable _per se_.
 Neither IMHO is the user-facing semantic split among old and new
 constructors.

 There are two separate issues here:

 1. Should Map.prototype be an instance (firstborn for its realm) of class
 Map?

 2. Should Map.prototype be a key/value store that can be used or abused as
 any other Map could be?

 We should not mix these up. SpiderMonkey (and possibly V8, I haven't
 tested) says yes to 1 and no to 2.


1: yes
2: no


Rick





 I did not specify that Map.prototype is a Map instance.  While it has
 the methods that are applicable to Map instances it does not the internal
 state that is necessary for those methods to actually work.  For example,
 if you try to store a value into Map.prototype by calling its set method,
 you will get a TypeErrior according to the specification. May.prototype can
 not be used as a map object.


 That doesn't mean Map.prototype should not be classified as a Map per 1
 above.


  Why did I do this?  Because, we are defining a significant number new
 built-in classes and it is going to be increasingly hard to define
 meaningful instance state for all such prototypes.


 Not so, as shown above. It's trivial in SpiderMonkey to give the prototype
 no instance state and check for that. Alternative implementation techniques
 are feasible with different trade-offs.

 Cc'ing implementors.

 /be


 __**_
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/**listinfo/es-discusshttps://mail.mozilla.org/listinfo/es-discuss

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-09-29 Thread Rick Waldron
On Sat, Sep 29, 2012 at 6:19 PM, Brendan Eich bren...@mozilla.org wrote:

 Allen Wirfs-Brock wrote:

 My intention, subject to feedback here and from TC39,  is to follow the
 pattern I used for Map as much as possible.  However, TypedArray object are
 all ready implemented by all major browsers to that may limit how we apply
 it to them.


 Implementations differ:

 javascript:alert(Object.**prototype.toString.call(**
 Uint8Array.prototype).slice(8,**-1))

 in Opera says Uint8Array, while in Firefox and Safari it says
 Uint8ArrayPrototype. Chrome says Object. I can't test IE here.


How common is that? Generally the [[Class]] (NativeBrand?) is derived via

Object.**prototype.toString.call(**Uint8Array).slice(8,**-1)

(sans .prototype)

Rick




 The typed array (http://www.khronos.org/**registry/typedarray/specs/**
 latest/ http://www.khronos.org/registry/typedarray/specs/latest/) does
 not specify.

 /be

 __**_
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/**listinfo/es-discusshttps://mail.mozilla.org/listinfo/es-discuss

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-09-29 Thread Brendan Eich

Rick Waldron wrote:
On Sat, Sep 29, 2012 at 6:19 PM, Brendan Eich bren...@mozilla.org 
mailto:bren...@mozilla.org wrote:


Allen Wirfs-Brock wrote:

My intention, subject to feedback here and from TC39,  is to
follow the pattern I used for Map as much as possible.
 However, TypedArray object are all ready implemented by all
major browsers to that may limit how we apply it to them.


Implementations differ:


javascript:alert(Object.prototype.toString.call(Uint8Array.prototype).slice(8,-1))

in Opera says Uint8Array, while in Firefox and Safari it says
Uint8ArrayPrototype. Chrome says Object. I can't test IE here.


How common is that?


Which that?


Generally the [[Class]] (NativeBrand?) is derived via

Object.prototype.toString.call(Uint8Array).slice(8,-1)

(sans .prototype)


s/derived/disclosed/

I'm saying typed arrays from khronos are underspecified, and 
implementations vary. Something to fix in ES6.


/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-09-29 Thread Mark S. Miller
On Sat, Sep 29, 2012 at 5:17 PM, Brendan Eich bren...@mozilla.org wrote:

 Allen Wirfs-Brock wrote:

 However, there is a bigger issue here.  You could have asked a similar
  question about Map.prototype.  Why isn't Map.prototype a Map instances? Is
 this a bug or an intentional design decision?

 Historically, the prototype objects associated with the 9 named built-in
 constructors were all defined to be instances of those constructors.  For
 example, Boolean.prototype is a Boolean instance whose value is false.

 In writing the specification for Map, I intentionally deviated from that
 pattern.


 Failing to consult with implementors will just make editing churn. I don't
 remember much discussion on this change,


FWIW, this isn't a change from what we've discussed, it's a return to what
we've discussed. The proposals at

http://wiki.ecmascript.org/doku.php?id=harmony:simple_maps_and_sets
http://wiki.ecmascript.org/doku.php?id=harmony:weak_maps
and
all the accepted class proposals including the recent maximin classes

use prototypes as Allen is now using them -- essentially as vtables, rather
than prototypical instances.

The fact that Date.prototype is a Date which therefore remains mutable
after freezing opened up a communications channel that SES closes at some
cost. Likewise with WeakMap.prototype on FF. Date.prototype is not a
working Date on IE and no one notices. RegExp.prototype used to not be a
RegExp, and no one noticed.

It's too late to make Date.prototype and RegExp.prototype not be Dates and
RegExps, but we should at least make them non-mutable once frozen. But
please let's not make the mistake with WeakMap.prototype, Map.prototype,
Set.prototype, and the prototype objects created for maximinimal classes.



 if any -- we did talk about the general problem of prototype objects being
 firstborns of their class, and how this makes them sometimes not just basis
 cases but degenerate cases.

 However, Map is prototyped in SpiderMonkey and V8. In SpiderMonkey, the
 prototype is a Map, not an Object:

 js Object.prototype.toString.**call(Map.prototype).slice(8, -1)
 Map

 but you can't get, has, set, size, or iterate Map.prototype:

 js Map.prototype.get('x')
 typein:2:0 TypeError: get method called on incompatible Map
 js Map.prototype.has('x')
 typein:3:0 TypeError: has method called on incompatible Map
 js Map.prototype.set('x', 42)
 typein:4:0 TypeError: set method called on incompatible Map
 js Map.prototype.size()
 typein:5:0 TypeError: size method called on incompatible Map
 js for (var [k, v] of Map.prototype) ;
 typein:6:13 TypeError: iterator method called on incompatible Map

 The error message is suboptimal but what's going on here is that
 Map.prototype has the SpiderMonkey equivalent of [[Class]] == Map (or the
 ES6 equivalent). This is important since all the builtins in ES3 + Reality
 (including RegExp; ES3 deviated there) make the prototype for built-in
 class C be of class C.

 Your change requires implementations to provide a different built-in class
 (constructor/prototype) initialization path. That's not desirable _per se_.
 Neither IMHO is the user-facing semantic split among old and new
 constructors.

 There are two separate issues here:

 1. Should Map.prototype be an instance (firstborn for its realm) of class
 Map?

 2. Should Map.prototype be a key/value store that can be used or abused as
 any other Map could be?

 We should not mix these up. SpiderMonkey (and possibly V8, I haven't
 tested) says yes to 1 and no to 2.


 I did not specify that Map.prototype is a Map instance.  While it has
 the methods that are applicable to Map instances it does not the internal
 state that is necessary for those methods to actually work.  For example,
 if you try to store a value into Map.prototype by calling its set method,
 you will get a TypeErrior according to the specification. May.prototype can
 not be used as a map object.


 That doesn't mean Map.prototype should not be classified as a Map per 1
 above.


  Why did I do this?  Because, we are defining a significant number new
 built-in classes and it is going to be increasingly hard to define
 meaningful instance state for all such prototypes.


 Not so, as shown above. It's trivial in SpiderMonkey to give the prototype
 no instance state and check for that. Alternative implementation techniques
 are feasible with different trade-offs.

 Cc'ing implementors.

 /be


 __**_
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/**listinfo/es-discusshttps://mail.mozilla.org/listinfo/es-discuss




-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-09-29 Thread Allen Wirfs-Brock

On Sep 29, 2012, at 5:17 PM, Brendan Eich wrote:

 Allen Wirfs-Brock wrote:
 However, there is a bigger issue here.  You could have asked a similar  
 question about Map.prototype.  Why isn't Map.prototype a Map instances? Is 
 this a bug or an intentional design decision?
 
 Historically, the prototype objects associated with the 9 named built-in 
 constructors were all defined to be instances of those constructors.  For 
 example, Boolean.prototype is a Boolean instance whose value is false.
 
 In writing the specification for Map, I intentionally deviated from that 
 pattern.
 
 Failing to consult with implementors will just make editing churn. I don't 
 remember much discussion on this change, if any -- we did talk about the 
 general problem of prototype objects being firstborns of their class, and how 
 this makes them sometimes not just basis cases but degenerate cases.

That's why I brought it up, so we can talk about it.  

But it's not a change, Map is new.  The strawman didn't address this issue 
unless you place significance in the fact that the spec. uses a class 
definition to specify the behavior of Map.   If you do consider that 
significant, then what I spec'ed is consistent with that because, as I pointed 
out in my message, ES6 class definitions don't maintain the prototype is an 
instance of the class invariant.

 
 However, Map is prototyped in SpiderMonkey and V8. In SpiderMonkey, the 
 prototype is a Map, not an Object:

How do you define is a Map?  

 
 js Object.prototype.toString.call(Map.prototype).slice(8, -1)
 Map
 

The draft spec. for Map will also produce this result.  But is returning Map 
from toString the condition make something a Map? (See the draft spec. for 
Object.prototype.toString)

 but you can't get, has, set, size, or iterate Map.prototype:
 
 js Map.prototype.get('x')
 typein:2:0 TypeError: get method called on incompatible Map
 js Map.prototype.has('x')
 typein:3:0 TypeError: has method called on incompatible Map
 js Map.prototype.set('x', 42)
 typein:4:0 TypeError: set method called on incompatible Map
 js Map.prototype.size()
 typein:5:0 TypeError: size method called on incompatible Map
 js for (var [k, v] of Map.prototype) ;
 typein:6:13 TypeError: iterator method called on incompatible Map

The draft spec. produces exactly these results (of course it doesn't provide 
the error message text).  However, for the above test cases of the 
SpiderMonkey,  if Map.prototype is really a Map instance then why don't these 
methods do something useful, rather than throwing a TypeError? get could return 
undefined, has could return false, size could be 0, @iterator, could return an 
empty iterator, etc.   To me, that is what is a Map means.  All the 
behaviors for Map instances work as specified.

 
 The error message is suboptimal but what's going on here is that 
 Map.prototype has the SpiderMonkey equivalent of [[Class]] == Map (or the 
 ES6 equivalent).

The equivalent in the spec. draft is to test whether or not the object is an 
implementation of the specified Map instance abstraction.  Within the draft 
spec. this is abstracted as testing whether or not the object has a 
[[MapData]] internal property.  How implementations choose to test that 
conditions and represent the associated state is their decision to make.


 This is important since all the builtins in ES3 + Reality (including RegExp; 
 ES3 deviated there) make the prototype for built-in class C be of class C.

Yes, but why is that important to anyone? In my earlier message on thus thread 
I argued that it is in fact unimportant and probably undesirable. Other than 
legacy consistency what makes this an important invariant to maintain?

 
 Your change requires implementations to provide a different built-in class 
 (constructor/prototype) initialization path. That's not desirable _per se_. 
 Neither IMHO is the user-facing semantic split among old and new 
 constructors.

There are costs and benefits of changes.  In this particular case, the 
implementation cost of supporting prototypes that are not also instances of 
their associated constructor seems likely to be very low.  As you mention, 
prior to ES5 RegExp was specified that way and it appears (at least for some 
implementations) that (some) DOM objects don't have the characteristic.

 
 There are two separate issues here:
 
 1. Should Map.prototype be an instance (firstborn for its realm) of class Map?
 
 2. Should Map.prototype be a key/value store that can be used or abused as 
 any other Map could be?
 
 We should not mix these up. SpiderMonkey (and possibly V8, I haven't tested) 
 says yes to 1 and no to 2.

I have no idea what you actually mean by an instance or firstborn of its 
realm.

In ES6 specifications. 1 and 2 above are the same thing.  Being an instance 
of a built-in constructor in those specifications means that an object has all 
of the internal and regular properties as specified for instances created by 
the constructor (except 

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

2012-09-29 Thread Allen Wirfs-Brock

On Sep 29, 2012, at 7:23 PM, Rick Waldron wrote:

 ...
 
 Subjectively, the examples here are exactly how I would expect (hope?) this 
 to behave, as the existing behaviour: 
 
  Array.prototype.push(1)
 1
  Array.prototype
 [ 1 ]
 
 
 ...Has always been seemed strange ;)
 

I believe this is the root item we are discussing.   The legacy precedent says 
that Map.prototype.set(screwed, you) should work and create an accessible 
map entry. 

I specified Map.prototype to throw.

 
 
 
 
 
  
 Your change requires implementations to provide a different built-in class 
 (constructor/prototype) initialization path. That's not desirable _per se_. 
 Neither IMHO is the user-facing semantic split among old and new 
 constructors.
 
 There are two separate issues here:
 
 1. Should Map.prototype be an instance (firstborn for its realm) of class Map?
 
 2. Should Map.prototype be a key/value store that can be used or abused as 
 any other Map could be?
 
 We should not mix these up. SpiderMonkey (and possibly V8, I haven't tested) 
 says yes to 1 and no to 2.
 
 1: yes
 2: no
 

As I covered in my reply to Brendan, I don't think these are sufficiently 
defined to really answer.  But if you definition of an instance is that 
Object.prototype.toString.call(Map.prototype) returns Map then the latest 
spec. draft does 1: yes, 2: no

Allen___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-09-29 Thread Allen Wirfs-Brock

On Sep 29, 2012, at 7:26 PM, Rick Waldron wrote:

 
 
 On Sat, Sep 29, 2012 at 6:19 PM, Brendan Eich bren...@mozilla.org wrote:
 Allen Wirfs-Brock wrote:
 My intention, subject to feedback here and from TC39,  is to follow the 
 pattern I used for Map as much as possible.  However, TypedArray object are 
 all ready implemented by all major browsers to that may limit how we apply it 
 to them.
 
 Implementations differ:
 
 javascript:alert(Object.prototype.toString.call(Uint8Array.prototype).slice(8,-1))
 
 in Opera says Uint8Array, while in Firefox and Safari it says 
 Uint8ArrayPrototype. Chrome says Object. I can't test IE here.
 
 How common is that? Generally the [[Class]] (NativeBrand?) is derived via
 
 Object.prototype.toString.call(Uint8Array).slice(8,-1)

Note that the intent of [[NativeBrand]] is not just a renaming of [[Class]].  
As the change notes for the latest draft stated, that draft as spec. for 
Object.prototype.toString that support an extensibility model that does not 
depend upon [[Class]]/[[NativeBrand]].  My hope is that we do not define any 
new [[Class]]/[[NativeBrand]] values other than the ones that are need to 
support its legacy use for nominal type testing of the 10 (or so) existing 
built-ins.  I also hope to use the new toString extension point in all the new 
built-ins.  You can see this in the Map specification.

Allen



___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-09-29 Thread Brendan Eich

Mark S. Miller wrote:
On Sat, Sep 29, 2012 at 5:17 PM, Brendan Eich bren...@mozilla.org 
mailto:bren...@mozilla.org wrote:


Allen Wirfs-Brock wrote:

However, there is a bigger issue here.  You could have asked a
similar  question about Map.prototype.  Why isn't
Map.prototype a Map instances? Is this a bug or an intentional
design decision?

Historically, the prototype objects associated with the 9
named built-in constructors were all defined to be instances
of those constructors.  For example, Boolean.prototype is a
Boolean instance whose value is false.

In writing the specification for Map, I intentionally deviated
from that pattern.


Failing to consult with implementors will just make editing churn.
I don't remember much discussion on this change,


FWIW, this isn't a change from what we've discussed, it's a return to 
what we've discussed. The proposals at


http://wiki.ecmascript.org/doku.php?id=harmony:simple_maps_and_sets
http://wiki.ecmascript.org/doku.php?id=harmony:weak_maps
and
all the accepted class proposals including the recent maximin classes

use prototypes as Allen is now using them -- essentially as vtables, 
rather than prototypical instances.


That conclusion assumes too much. You don't need Object instance 
prototypes. You simply need immutable/degenerate/unusable prototypes of 
the same class as the constructor instantiates.


Did you read further down?


Your change requires implementations to provide a different
built-in class (constructor/prototype) initialization path. That's
not desirable _per se_. Neither IMHO is the user-facing semantic
split among old and new constructors.

There are two separate issues here:

1. Should Map.prototype be an instance (firstborn for its realm)
of class Map?

2. Should Map.prototype be a key/value store that can be used or
abused as any other Map could be?

We should not mix these up. SpiderMonkey (and possibly V8, I
haven't tested) says yes to 1 and no to 2.



V8 and SpiderMonkey agree. This avoids making two paths for built-in 
constructor.prototype creation, one that makes a degenerate firstborn of 
the class at hand, the other than makes an Object-instance prototype.


Why introduce this irregularity if it's not necessary to avoid the 
communication channel?


/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-09-29 Thread Mark S. Miller
On Sat, Sep 29, 2012 at 10:14 PM, Brendan Eich bren...@mozilla.org wrote:

 Mark S. Miller wrote:

  On Sat, Sep 29, 2012 at 5:17 PM, Brendan Eich bren...@mozilla.orgmailto:
 bren...@mozilla.org wrote:

 Allen Wirfs-Brock wrote:

 However, there is a bigger issue here.  You could have asked a
 similar  question about Map.prototype.  Why isn't
 Map.prototype a Map instances? Is this a bug or an intentional
 design decision?

 Historically, the prototype objects associated with the 9
 named built-in constructors were all defined to be instances
 of those constructors.  For example, Boolean.prototype is a
 Boolean instance whose value is false.

 In writing the specification for Map, I intentionally deviated
 from that pattern.


 Failing to consult with implementors will just make editing churn.
 I don't remember much discussion on this change,


 FWIW, this isn't a change from what we've discussed, it's a return to
 what we've discussed. The proposals at

 http://wiki.ecmascript.org/**doku.php?id=harmony:simple_**maps_and_setshttp://wiki.ecmascript.org/doku.php?id=harmony:simple_maps_and_sets
 http://wiki.ecmascript.org/**doku.php?id=harmony:weak_mapshttp://wiki.ecmascript.org/doku.php?id=harmony:weak_maps
 and
 all the accepted class proposals including the recent maximin classes

 use prototypes as Allen is now using them -- essentially as vtables,
 rather than prototypical instances.


 That conclusion assumes too much. You don't need Object instance
 prototypes. You simply need immutable/degenerate/unusable prototypes of the
 same class as the constructor instantiates.

 Did you read further down?


(sheepishly) I did after.





  Your change requires implementations to provide a different
 built-in class (constructor/prototype) initialization path. That's
 not desirable _per se_. Neither IMHO is the user-facing semantic
 split among old and new constructors.

 There are two separate issues here:

 1. Should Map.prototype be an instance (firstborn for its realm)
 of class Map?

 2. Should Map.prototype be a key/value store that can be used or
 abused as any other Map could be?

 We should not mix these up. SpiderMonkey (and possibly V8, I
 haven't tested) says yes to 1 and no to 2.


 V8 and SpiderMonkey agree. This avoids making two paths for built-in
 constructor.prototype creation, one that makes a degenerate firstborn of
 the class at hand, the other than makes an Object-instance prototype.

 Why introduce this irregularity if it's not necessary to avoid the
 communication channel?


I agree that the only security issue is avoiding the communications channel.

Security aside, given maximin

class Foo

what do you suggest Foo.prototype be?





 /be




-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-09-29 Thread Brendan Eich

Allen Wirfs-Brock wrote:
As I covered in my reply to Brendan, I don't think these are 
sufficiently defined to really answer.  But if you definition of an 
instance is that Object.prototype.toString.call(Map.prototype) 
returns Map then the latest spec. draft does 1: yes, 2: no


That's precisely at issue, and the two questions are sufficiently 
well-defined: neither over- nor under-specified.


Implementations must be able to make firstborn prototypes uniformly. 
This is what killed ES3's overreaction that tried to make 
RegExp.prototype be an Object instance.


Yes, it's too bad ES3 (and ES1 with Date.prototype) left mutable junk in 
built-in prototypes, but those ships sailed. We can do better without 
requiring Object instances as built-in prototypes, which was Yusuke 
raised for DataView that started this thread.


Does DataView.prototype need any special handling in the ES6 draft?

/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-09-29 Thread Brendan Eich

Mark S. Miller wrote:

Security aside, given maximin

class Foo

what do you suggest Foo.prototype be?


If classes are sugar for constructor functions, an Object instance, just 
as you'd get for


  function Foo(){}
  Foo.prototype

There has always been an unsightly difference between built-in 
constructors and user-defined ones. Whether or how we reduce that gulf 
is separable from what the [[NativeBrand]] or [[Class]] of a built-in's 
prototype should be.


When self-hosting built-ins, this matters. Suppose [[NativeBrand]] could 
be a symbol private to the built-ins. That would allow the engine to set 
up bespoke-looking prototypes as it needs to for ES1-5 compatibility. 
But should user-defined classes have access to this symbol?


/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-09-29 Thread Yusuke Suzuki

 Mark S. Miller wrote:

 Security aside, given maximin

 class Foo

 what do you suggest Foo.prototype be?


I suggest adding @@toStringTag:Foo property to Foo.prototype when `class
Foo` is executed.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-09-29 Thread Mark S. Miller
On Sat, Sep 29, 2012 at 10:21 PM, Mark S. Miller erig...@google.com wrote:


 I agree that the only security issue is avoiding the communications
 channel.

 Security aside, given maximin

 class Foo

 what do you suggest Foo.prototype be?


That was too vague. Reformulating.

Private properties, i.e., properties named by symbols, are the class analog
to the internal properties of the built ins. The current [[Class]] tests in
ES5 are there essentially to ensure that these internal properties exist
and satisfy whatever invariant is assumed. In maximin classes, we don't
expand methods with an analog of that [[Class]] check. Rather, the presence
of these private symbol-named properties implicitly provides the branding.
Say class Foo uses symbol @s to name a private instance property of
instances of Foo, and that method bar() of Foo accesses this @s property,
failing if the object doesn't have an @s. Clearly, bar() should fail on
Foo.prototype just as it should fail on any non-instance of Foo. This is
already implied by the mechanisms proposed for installing private instance
variables.

-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2012-09-29 Thread Norbert Lindenberg
Last week TC 39 approved a standard defining three new built-in constructors 
whose instances and prototype objects all have [[Class]] Object. Also, the 
prototype objects are not constructed by their respective constructors, but 
initialized by them, e.g., as Intl.Collator.call({}).

Are you suggesting they should have Collator, NumberFormat, and 
DateTimeFormat, respectively, and the prototypes be specified as being 
constructed by their constructors?

Thanks,
Norbert


On Sep 29, 2012, at 22:24 , Brendan Eich wrote:

 Mark S. Miller wrote:
 Security aside, given maximin
 
class Foo
 
 what do you suggest Foo.prototype be?
 
 If classes are sugar for constructor functions, an Object instance, just as 
 you'd get for
 
  function Foo(){}
  Foo.prototype
 
 There has always been an unsightly difference between built-in constructors 
 and user-defined ones. Whether or how we reduce that gulf is separable from 
 what the [[NativeBrand]] or [[Class]] of a built-in's prototype should be.
 
 When self-hosting built-ins, this matters. Suppose [[NativeBrand]] could be a 
 symbol private to the built-ins. That would allow the engine to set up 
 bespoke-looking prototypes as it needs to for ES1-5 compatibility. But should 
 user-defined classes have access to this symbol?
 
 /be
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss