Re: Standard builtins' prototypes and toString

2014-06-18 Thread Brendan Eich

Allen Wirfs-Brock wrote:

"[ object ???]"


"[object WTF]"

:-P

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


Re: @@new

2014-06-18 Thread Allen Wirfs-Brock
For background, here is the original proposal presentation about using @@create 
to enable subclassing of built-ins.
   
http://wiki.ecmascript.org/lib/exe/fetch.php?id=meetings%3Ameeting_jan_29_2013&cache=cache&media=meetings:subclassing_builtins.pdf
 

In particular see material that starts at slide 19. In this proposal, the 
initialized/uninitialized state isn't really about ensuring that an object has 
be correctly initialized. It's more about distinguishing calls to the the 
constructor as a factory(possibly a name-spaced factory or a factory installed 
as a method of another object) from calls (or super calls) to the constructor 
to initialize an instance. 

Allen



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


Re: Standard builtins' prototypes and toString

2014-06-18 Thread Allen Wirfs-Brock

On Jun 18, 2014, at 4:12 PM, Brendan Eich wrote:

> Allen Wirfs-Brock wrote:
>> The spec. current says throw for this Symbol.prototype case.  The 
>> (reasonable) opposing view is that toString should never throw.  Other than 
>> the protoype-is-not-an-instance it all about unlikely edge cases where 
>> toString methods are applied to the wrong kind of object.
> 
> js> Object.create(null).toString()
> typein:1:0 TypeError: Object.create(...).toString is not a function
> 
> It happens. Better to catch that error (Symbol.prototype flowing into an 
> implicit conversion) early?

which is pretty much the approach the ES6 spec. has taken WRT toString up to 
now. Tension between catching invalid iplicit toString conversions and reliable 
toString for debugging. 

At any rate, run time tools can really depend upon toString working,  They 
probably should use something like:

function reliableToString(obj) {
   try {return obj.toString()} catch (e) {
   try {return {}.toString.call(obj)} catch (f) {
 return "[ object ???]"}
}
}
}

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


Re: Standard builtins' prototypes and toString

2014-06-18 Thread Brendan Eich

Allen Wirfs-Brock wrote:
The spec. current says throw for this Symbol.prototype case.  The 
(reasonable) opposing view is that toString should never throw.  Other 
than the protoype-is-not-an-instance it all about unlikely edge cases 
where toString methods are applied to the wrong kind of object.


js> Object.create(null).toString()
typein:1:0 TypeError: Object.create(...).toString is not a function

It happens. Better to catch that error (Symbol.prototype flowing into an 
implicit conversion) early?


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


Re: @@new

2014-06-18 Thread Kevin Smith
> I think Allen's suggestion of providing constructor arguments to @@create
is promising.  That would allow the implementation to allocate and
initialize an object in one go, if desired.  That seems to embody the
advantages of fusing initialization and allocation, without the headache
for the user.
>
>

Never mind,  that doesn't work. Sorry for the noise.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Standard builtins' prototypes and toString

2014-06-18 Thread Allen Wirfs-Brock

On Jun 18, 2014, at 2:38 PM, Brendan Eich wrote:
> 
> 
>> For example, what should Symbol.prototype.toString() do? (b) sounds like a 
>> good choice for it.  (c) is certainly ok, for Date.prototype but but we have 
>> other cases that need to be addressed.
> 
> Symbol.prototype could even throw, it's such an outlier. Throw if no "zero" 
> might go a long way, cover most of the dog.

The spec. current says throw for this Symbol.prototype case.  The (reasonable) 
opposing view is that toString should never throw.  Other than the 
protoype-is-not-an-instance it all about unlikely edge cases where toString 
methods are applied to the wrong kind of object.

Allen

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


Re: Standard builtins' prototypes and toString

2014-06-18 Thread Mark S. Miller
On Wed, Jun 18, 2014 at 2:38 PM, Brendan Eich  wrote:
>
>
> [...] Throw if no "zero" might go a long way, cover most of the dog.


Is there a cartoonist in the house?



>
>
> /be
>



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


Re: Standard builtins' prototypes and toString

2014-06-18 Thread Brendan Eich

Allen Wirfs-Brock wrote:

Mostly about establishing the pattern for what should be done for other toString methods 
that are applied to the wrong kind of object or a non-instance prototype.  Not every 
object that could get a custom toString has a natural "0-value".


Don't let the tail wag the dog here.

That's on top of "avoid risk you can't size easily and don't need".


For example, what should Symbol.prototype.toString() do? (b) sounds like a good 
choice for it.  (c) is certainly ok, for Date.prototype but but we have other 
cases that need to be addressed.


Symbol.prototype could even throw, it's such an outlier. Throw if no 
"zero" might go a long way, cover most of the dog.


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


Re: Standard builtins' prototypes and toString

2014-06-18 Thread Allen Wirfs-Brock

On Jun 18, 2014, at 11:04 AM, Brendan Eich wrote:

> I held back but can't any longer.
> 
> Till Schneidereit wrote:
>> 
>> 
>>As far as I can tell, toString being an issue is just a conjecture
>>that hasn't been tested. So, you could even go ahead an implement
>>the corresponding toString methods as currently stands in the ES6
>>spec. (throw for the wrong kind of object) which probably requires
>>no change to their current implementation.
>> 
>> 
>> I'm somewhat opposed to this for two reasons:
>> 
>> One is that I'm pretty sure that it won't be compatible, whereas I'm 
>> optimistic about making Date.prototype a non-Date. There are tens of 
>> thousands of people using Nightly as their default browser, and while that 
>> makes it a good first target for experiments like this, it also means that 
>> we shouldn't do experiments where we're not optimistic about the outcome.
>> 
>> The other is that I still think the standard library shouldn't contain 
>> objects that throw when they're string-ified or value-ified.
> 
> Agreed on both points.
> 
> Changing Date.prototype from how it has stringified for (now) over 19 years 
> [1] takes unknown probabiltiy times non-trivial cost risk, and Firefox 
> Nightly won't be enough to find the content that breaks (sorry). Other 
> engines would need to test and even put into release channels the change, and 
> then we'd hope some smart site bug diag guru figures out the problem, if 
> there is a problem.
> 
> Best way to avoid this is to avoid it. What's the profit in (b)?

Mostly about establishing the pattern for what should be done for other 
toString methods that are applied to the wrong kind of object or a non-instance 
prototype.  Not every object that could get a custom toString has a natural 
"0-value".

For example, what should Symbol.prototype.toString() do? (b) sounds like a good 
choice for it.  (c) is certainly ok, for Date.prototype but but we have other 
cases that need to be addressed.

Allen




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


Re: @@new

2014-06-18 Thread Kevin Smith
>
>
> function F(x) { /* ??? the initial message really isn't explicit about
> what does here */ };
> F[Symbol.new] = {[Symbol.new](x) {  //use an object literal to create a
> "method" kind of function
> var obj = super();
> obj.foo = x
> }}[Symbol.new].toMethod(F);
>
> which is quite different from you get for:
>
>  function F(x) {this.foo=x};
>

Yes - the proposed semantics are quite different.  The whole thrust of the
proposal is to fuse initialization and allocation, which is completely at
odds with how user-defined "classes" work in ES5.

I think Allen's suggestion of providing constructor arguments to @@create
is promising.  That would allow the implementation to allocate and
initialize an object in one go, if desired.  That seems to embody the
advantages of fusing initialization and allocation, without the headache
for the user.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: @@new

2014-06-18 Thread Allen Wirfs-Brock

On Jun 18, 2014, at 1:43 PM, Brendan Eich wrote:

> Allen Wirfs-Brock wrote:
>>> Not so much to me, and one could argue for static [@@new](){} sugar 
>>> similarly.
>> 
>> I think that fact that these really are semantically equivalent:
>> 
>>  function F(x) {this.foo=x};
>>  class F  {constructor(x) {this.foo=x}};
>> 
>> is pretty important to the evolutionary nature ES6 classes.
> 
> Jason covered the combinations: his proposal supports class subclassing 
> function, etc. What concretely do you mean here, if not that? If you mean 
> refactoring from one to the other, what observably differs?

My understanding of the proposal was that:

class F  {constructor(x) {this.foo=x}};

turns into the equivalent of:

function F(x) { /* ??? the initial message really isn't explicit about what 
does here */ };
F[Symbol.new] = {[Symbol.new](x) {  //use an object literal to create a 
"method" kind of function
var obj = super();
obj.foo = x
}}[Symbol.new].toMethod(F);

which is quite different from you get for:

 function F(x) {this.foo=x};

allen

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


Re: @@new

2014-06-18 Thread Boris Zbarsky

On 6/18/14, 3:14 PM, Anne van Kesteren wrote:

Revisiting existing classes and making them suitable for subclassing
seems like something that would be hard to avoid.


I think the difference for me is whether making a class subclassable 
before careful auditing means potentially introducing suboptimal 
behavior (that we presumably fix when either we do the audit or someone 
reports a bug) or whether it means potentially introducing a security bug.


In the former case, we can conceivably allow subclassing immediately 
(possibly only in nightly builds or whatnot) and then work on resolving 
the issues people find.  In the latter case the auditing needs to be a 
lot more stringent before subclassing is allowed, and allowing 
subclassing without auditing is just a non-starter.  I'm OK shipping 
somewhat buggy code for people to experiment with in nightly builds, but 
I'm not OK shipping security bugs.


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


Re: @@new

2014-06-18 Thread Brendan Eich

Allen Wirfs-Brock wrote:

Not so much to me, and one could argue for static [@@new](){} sugar similarly.


I think that fact that these really are semantically equivalent:

  function F(x) {this.foo=x};
  class F  {constructor(x) {this.foo=x}};

is pretty important to the evolutionary nature ES6 classes.


Jason covered the combinations: his proposal supports class subclassing 
function, etc. What concretely do you mean here, if not that? If you 
mean refactoring from one to the other, what observably differs?


Again it's important to separate independent parts of the 
counter-proposal (which even Jason is changing, e.g. no diff between C() 
and new C()). The high order bit remains the uninitialized observability 
of the draft-ES6 way.


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


Re: @@new

2014-06-18 Thread C. Scott Ananian
On Wed, Jun 18, 2014 at 3:08 PM, Allen Wirfs-Brock
 wrote:
> I think that fact that these really are semantically equivalent:
>
>  function F(x) {this.foo=x};
>  class F  {constructor(x) {this.foo=x}};
>
> is pretty important to the evolutionary nature ES6 classes.

That's the easy case.  The `class F` version in Jason's proposal
invokes a superclass constructor, but that does nothing so it's all
the same.

The harder question is:
```
function F(x) { this.x = x; }
function G(y) { this.y = y; }
G.prototype = new F;
```
vs
```
function F(x) { this.x = x; }
class G extends F { constructor(y) { this.y = y; } }
```
  --scott
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: @@new

2014-06-18 Thread Anne van Kesteren
On Wed, Jun 18, 2014 at 9:01 PM, Boris Zbarsky  wrote:
> Note that at this point we're already forcing spec authors to think about
> the exact @@create behavior to make things subclassable and that in
> particular, every single existing spec that has a constructor will need to
> be revisited and modified as needed.

Revisiting existing classes and making them suitable for subclassing
seems like something that would be hard to avoid. Allen had to do it
for all the built-in classes to make sure certain methods return
this.constructor and such, I doubt we're going to avoid that.


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


Re: @@new

2014-06-18 Thread Allen Wirfs-Brock

On Jun 18, 2014, at 11:41 AM, Brendan Eich wrote:

> Allen Wirfs-Brock wrote:
>> Except in the current design there is no special reinterpretation of the 
>> constructor method body semantics.  The constructor method definition simply 
>> provides body of the constructor function and semantically is exactly the 
>> same as the body that is provided in a Function definition. See 
>> http://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-classdefinitionevaluation
>>  
>> 
>>  and in particular step 10 which calls 
>> http://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-definemethod
>>  
>> 
>>  which just calls 
>> http://people.mozilla.org/~jorendorff/es6-draft.html#sec-functioncreate 
>>  
>> .  No special processing of the body anywhere along that path.  The only 
>> special treatment prior to step 10 is
  about choosing a default constructor body if a constructor method isn't 
provided in the class declaration.
> 
> Fair point, things have changed. Still, here are some other bits of magic 
> that make constructor(){} as ClassElement not just a method definition. 
> Here's another:
> 
> * 'constructor' is not enumerable but methods are.
> 
Yes, but that's just preserving the 'constructor' property attribute 
conventions established by function definition.  Nothing to do with the 
semantics of the actual constructor body or that a "class" object".

>> 
>> It is an alternative syntax for providing a the body of a function, but it 
>> has no unique semantics.  That seems significant to me.
> 
> Not so much to me, and one could argue for static [@@new](){} sugar similarly.

I think that fact that these really are semantically equivalent:

 function F(x) {this.foo=};
 class F  {constructor(x) {this.foo=x}};

is pretty important to the evolutionary nature ES6 classes.

> 
> The most important thing here (I agree with Andreas R.) is -- if possible -- 
> avoiding uninitialized object observability.

I agree that uninitialized observability is a pain and has been a on-going 
source of reentrancy bugs in the the more complex built-in constructors.  I 
want to explore whether making the constructor arguments available to @@create 
provides an alternative way to eliminate that issue.

Also, much of the initialization checking complexity in the legacy built-ins is 
about maintain backwards compatibility for edgy use cases (for example, 
installing a built-in constructor that has factory called behavior as an 
instance method on one of its instances and then invoking it as as a method).  
Jason's explicit split between "called as a function" and "called as a method" 
make it easier to specify that but I'm not sure the other forward facing 
complexities it introduces is worth the spec. simplification we get for a few 
legacy built-in constructors.

There is a lot of legacy compatibility vs. future functionality trade-offs that 
have been made in the current design. It's good to look at those trade-off and 
see if any of them need to be rebalanced.  But we need to be careful about the 
scope of changes we are considering and whether in the end we actually get to a 
better place.  

Allen

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


Re: @@new

2014-06-18 Thread Boris Zbarsky

On 6/18/14, 1:58 PM, Erik Arvidsson wrote:

This particular one can be done because if the constructor returns an
object that is used instead.


Ah, I see.


This is an ugly pattern so it is discouraged


Especially given that it requires special care when subclassing somethin 
with such a constructor, correct?


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


Re: @@new

2014-06-18 Thread Boris Zbarsky

On 6/18/14, 2:54 PM, Domenic Denicola wrote:

Much the same, from what I understand. The parser needs to be able to create 
elements, including custom elements


Most "DOM" objects being added nowadays are not elements at all.  We 
need a less ambiguous name for "web platform things".  I've sometimes 
called them "IDL objects" or "Web IDL objects", but that's not all that 
clear either..


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


Re: @@new

2014-06-18 Thread Boris Zbarsky

On 6/18/14, 1:46 PM, Domenic Denicola wrote:

Yes, although in this case no initialization checks are necessary, just brand 
checks.


Well.  That depends on the desired behavior.

For example, say you have a DOMPoint as in your example above that is 
supposed to return Numbers for x and y.


In your pseudocode, what happens if .x or .y is accessed after @@create 
but before the constructor runs?  That depends on what slot 
initialization, if any, allocateNativeObjectWithSlots performs.  If a 
spec author wanted to not depend on implementation details like that, 
they would need to define that @@create puts something in the slots 
separate from whatever work the constructor does.


Note that at this point we're already forcing spec authors to think 
about the exact @@create behavior to make things subclassable and that 
in particular, every single existing spec that has a constructor will 
need to be revisited and modified as needed.


Doing an initialization check instead of a brand check would avoid 
needing to define @@create behavior in that sort of detail, I think, but 
adds extra checks that need to be performed, in addition to the brand 
check, and extra state (initialized or not) to be stored.



Given how few DOM objects have reasonable constructors to begin with


I'm not sure how you're defining "reasonable", but a quick look at 
Gecko's IDL shows 136 IDL files that have at least constructor in them 
that takes some arguments and does not simply take a single optional 
argument (a dictionary, say).  For comparison, we have 586 IDL files 
total...


Some of these are not standards yet, and a few I think have a 
no-argument constructor in addition to the one with arguments, and a 
bunch are event constructors that would all presumably be defined in a 
similar way in the spec, but I think you're significantly 
underestimating the number of things that have constructors that 
actually do something with their arguments.


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


Re: @@new

2014-06-18 Thread Erik Arvidsson
On Wed, Jun 18, 2014 at 2:54 PM, Domenic Denicola <
dome...@domenicdenicola.com> wrote:

> From: Brendan Eich 
>
> > This all looks at the past, where the DOM is warty as hell (I can say
> that, I started it). What about the future?
>
> Much the same, from what I understand. The parser needs to be able to
> create elements, including custom elements, without knowing what their
> constructor signature is. As specced [1], registering the element will set
> its @@create value to something that creates the element in this way, and
> presumably the parser will be updated to invoke @@create. (This is the same
> as how, in ES5, the parser invokes the `createdCallback` property passed to
> `registerElement`.)
>
> Dmitri, did I get that right?
>

Channeling Dimitri here since I designed that part...

The important part for Custom Elements is that @@create is non
configurable, non writable so that we can use a native implementation that
sets up all the internal wrapper pointers and whatnot. This is so that the
parser does not have to call into user code at parse time.

However, this still allows user code to provide a constructor that gets
invoked when doing `new MyCustomElement(x, y, z)`.


>
> [1]: https://w3c.github.io/webcomponents/spec/custom/#es6
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>



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


RE: @@new

2014-06-18 Thread Domenic Denicola
From: Brendan Eich 

> This all looks at the past, where the DOM is warty as hell (I can say that, I 
> started it). What about the future?

Much the same, from what I understand. The parser needs to be able to create 
elements, including custom elements, without knowing what their constructor 
signature is. As specced [1], registering the element will set its @@create 
value to something that creates the element in this way, and presumably the 
parser will be updated to invoke @@create. (This is the same as how, in ES5, 
the parser invokes the `createdCallback` property passed to `registerElement`.)

Dmitri, did I get that right?

[1]: https://w3c.github.io/webcomponents/spec/custom/#es6
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Standard builtins' prototypes and toString

2014-06-18 Thread Jason Orendorff
On Wed, Jun 18, 2014 at 1:04 PM, Brendan Eich  wrote:
> Just use "Invalid Date" and get on with more important work. My 2 cents.

Endorse. Can we get that added to the spec as normative text? ;-)

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


Re: @@new

2014-06-18 Thread Brendan Eich

Brendan Eich wrote:

Still, here


Er, "there"

are some other bits of magic that make constructor(){} as ClassElement 
not just a method definition. Here's another:


* 'constructor' is not enumerable but methods are. 


Someone should compile the complete list.

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


Re: @@new

2014-06-18 Thread Brendan Eich

Allen Wirfs-Brock wrote:
Except in the current design there is no special reinterpretation of 
the constructor method body semantics.  The constructor method 
definition simply provides body of the constructor function and 
semantically is exactly the same as the body that is provided in a 
Function definition. See 
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-classdefinitionevaluation 
 and 
in particular step 10 which calls 
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-definemethod 
 which 
just calls 
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-functioncreate  . 
 No special processing of the body anywhere along that path.  The only 
special treatment prior to step 10 is about choosing a default 
constructor body if a constructor method isn't provided in the class 
declaration.


Fair point, things have changed. Still, here are some other bits of 
magic that make constructor(){} as ClassElement not just a method 
definition. Here's another:


* 'constructor' is not enumerable but methods are.



It is an alternative syntax for providing a the body of a function, 
but it has no unique semantics.  That seems significant to me.


Not so much to me, and one could argue for static [@@new](){} sugar 
similarly.


The most important thing here (I agree with Andreas R.) is -- if 
possible -- avoiding uninitialized object observability.


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


Re: @@new

2014-06-18 Thread Allen Wirfs-Brock
On Jun 18, 2014, at 11:18 AM, Jason Orendorff wrote:

>> If so it seems like the question of whether to keep or drop the `new super` 
>> syntax is 100% orthogonal to your proposal.
> 
> I think that's right. I assumed the use cases for `new super` must be
> something to do with how objects are constructed now, but on
> reflection I don't know what the use cases are.

It's there now mostly just for syntactic consistency.  You can say 'new this' 
so why wouldn't you be able to say 'new super'.  It probably has limited use 
cases but it is one of those things that falls out of the overall expression 
syntax and I think if somebody does have a use case it would be surprising that 
it isn't allowed.

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


Re: @@new

2014-06-18 Thread C. Scott Ananian
On Wed, Jun 18, 2014 at 2:18 PM, Jason Orendorff
 wrote:
> I had a syntactic restriction on `super` for two reasons, neither one
> related to the kind of invariant you're thinking of: (1) if the
> super() call isn't there, I wanted to call it implicitly, for
> convenience and correctness-by-default; and, (2) until you call the
> base class @@new, there is no `this` value. But the syntactic
> restriction isn't sufficient for purpose #2, and besides none of us
> like it, so I will try to find another way. :)

Just for the record, Java maintains a similar syntactic/semantic
invariant on the use of `super`, so it can certainly be made to work.
On the other hand, it's also entirely true that nobody likes it very
much in Java, although they live can live with it (and there are
workarounds, like making one of the arguments a call to a static
method to do important work before the superclass constructor is
invoked).
  --scott
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: @@new

2014-06-18 Thread Allen Wirfs-Brock

On Jun 18, 2014, at 11:09 AM, Brendan Eich wrote:

> Allen Wirfs-Brock wrote:
>> This is also one of my bigger concerns.  I think the rewriting and 
>> reinterpretation of what the use wrote as a a constructor may be very 
>> problematic.   For example,how does this get translated:
>> 
>> class extends C {
>>  constructor() {
>>   super();
>>   super.foo();  //apply the inherited foo method to the new object
>>  }
>> }
>> 
>> If we had a design that didn't require the rewriting of the user provided 
>> constructor I'd be much more comfortable.  Thinking...more latter...
> 
> I used to think this way, but dherman pointed out years ago that constructor 
> in ES6 class is a special form, even though it looks like a method. Here's an 
> es-discuss thread from three years ago:
> 
> http://esdiscuss.org/topic/why-not-new-instead-of-constructor

Except in the current design there is no special reinterpretation of the 
constructor method body semantics.  The constructor method definition simply 
provides body of the constructor function and semantically is exactly the same 
as the body that is provided in a Function definition. See 
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-classdefinitionevaluation
 and in particular step 10 which calls 
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-definemethod
 which just calls 
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-functioncreate .  No 
special processing of the body anywhere along that path.  The only special 
treatment prior to step 10 is about choosing a default constructor body if a 
constructor method isn't provided in the class declaration.

It is an alternative syntax for providing a the body of a function, but it has 
no unique semantics.  That seems significant to me.

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


Re: @@new

2014-06-18 Thread Jason Orendorff
On Wed, Jun 18, 2014 at 1:40 AM, David Herman  wrote:
> You're inlining the method body into the @@new body, but I want to make sure 
> I understand what the specification of the Point function itself would be. 
> You've said Point !== Point[@@new] but calling Point(...args) should behave 
> the same as new Point(...args). So then would the specification of the Point 
> function's behavior just be to delegate to Point[@@new](...args)?

Yes, but that's not central to the proposal.

As it stands in the current draft, Point() would throw a TypeError,
because it tries to set `this.x = x` and `this` would be undefined. We
could keep the semantics exactly as they are even with @@new: just run
the body of the constructor function... It wouldn't be useful though,
just weird. I dunno, the status quo is weird. I don't feel strongly
about this.

>> The "super Arguments" call syntax in the ES6 drafts would be constrained to
>> appear only at the top of a constructor, as in Java:
>
> This part is what I'm the most unclear about. What invariant are you trying 
> to maintain? It seems like you're using this to attempt to guarantee that all 
> superclasses have had the chance to initialize their internal fields before 
> user code starts running, [...]
> But maybe I'm misunderstanding what invariant you're aiming at?

Yeah. I don't care about the new method itself leaking `this`. I just
want to make sure it's *possible* for a class implemented with
reasonable care to initialize its instances fully before exposing
them---and prove it, by making the ES6 builtin classes do so.

I had a syntactic restriction on `super` for two reasons, neither one
related to the kind of invariant you're thinking of: (1) if the
super() call isn't there, I wanted to call it implicitly, for
convenience and correctness-by-default; and, (2) until you call the
base class @@new, there is no `this` value. But the syntactic
restriction isn't sufficient for purpose #2, and besides none of us
like it, so I will try to find another way. :)

>> *   Base class constructors are always called.
>
> Are you saying you would not only restrict the super call to the top, but 
> require one to always be there? Or would an absence of a super call imply an 
> implicit `super()`?

The latter.

>> *   These productions would be dropped from the ES6 grammar:
>>
>>MemberExpression : new super Arguments
>>NewExpression : new super
>
> Clearly with your design `super[Symbol.new](...args)` is equivalent to `new 
> super`. Is it also emulate-able in the @@create semantics also?

I think yes, if we drop [[Construct]] as Allen separately proposed. As
long as [[Construct]] exists as a separate internal method, `new
super` is inconvenient to simulate.

> If so it seems like the question of whether to keep or drop the `new super` 
> syntax is 100% orthogonal to your proposal.

I think that's right. I assumed the use cases for `new super` must be
something to do with how objects are constructed now, but on
reflection I don't know what the use cases are.

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


Re: @@new

2014-06-18 Thread Brendan Eich

Domenic Denicola wrote:

I am not sure there are too many cases where there's an interesting distinction 
between allocated and initialized for the DOM, though. Given how few DOM 
objects have reasonable constructors to begin with, it seems like most of their 
work is being done (conceptually) in [Symbol.create]() anyway.


This all looks at the past, where the DOM is warty as hell (I can say 
that, I started it). What about the future?


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


Re: @@new

2014-06-18 Thread Brendan Eich

Allen Wirfs-Brock wrote:
This is also one of my bigger concerns.  I think the rewriting and 
reinterpretation of what the use wrote as a a constructor may be very 
problematic.   For example,how does this get translated:


class extends C {
  constructor() {
   super();
   super.foo();  //apply the inherited foo method to the new object
  }
}

If we had a design that didn't require the rewriting of the user 
provided constructor I'd be much more comfortable.  Thinking...more 
latter...


I used to think this way, but dherman pointed out years ago that 
constructor in ES6 class is a special form, even though it looks like a 
method. Here's an es-discuss thread from three years ago:


http://esdiscuss.org/topic/why-not-new-instead-of-constructor

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


Re: Standard builtins' prototypes and toString

2014-06-18 Thread Brendan Eich

I held back but can't any longer.

Till Schneidereit wrote:



As far as I can tell, toString being an issue is just a conjecture
that hasn't been tested. So, you could even go ahead an implement
the corresponding toString methods as currently stands in the ES6
spec. (throw for the wrong kind of object) which probably requires
no change to their current implementation.


I'm somewhat opposed to this for two reasons:

One is that I'm pretty sure that it won't be compatible, whereas I'm 
optimistic about making Date.prototype a non-Date. There are tens of 
thousands of people using Nightly as their default browser, and while 
that makes it a good first target for experiments like this, it also 
means that we shouldn't do experiments where we're not optimistic 
about the outcome.


The other is that I still think the standard library shouldn't contain 
objects that throw when they're string-ified or value-ified.


Agreed on both points.

Changing Date.prototype from how it has stringified for (now) over 19 
years [1] takes unknown probabiltiy times non-trivial cost risk, and 
Firefox Nightly won't be enough to find the content that breaks (sorry). 
Other engines would need to test and even put into release channels the 
change, and then we'd hope some smart site bug diag guru figures out the 
problem, if there is a problem.


Best way to avoid this is to avoid it. What's the profit in (b)?



If we run into an actual toString issue we will have a better idea
of which fix may be preferable.


How is that? The script-visible differences between #b and #c would 
mostly be that Date.prototype.toString would return "[Object Date]"


(Lower-case "object" there.)

for #b and (as it does now) "Invalid Date" for #c. It's not clear to 
me how testing the spec status quo would give us any more information 
about which one of these would be more compatible or preferable on 
other grounds.


Just use "Invalid Date" and get on with more important work. My 2 cents.

/be

[1] SpiderMonkey session:

js> Date.prototype.toString()
"Invalid Date"
js> Date.prototype.toSource()
"(new Date(NaN))"
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: @@new

2014-06-18 Thread Erik Arvidsson
On Wed, Jun 18, 2014 at 1:07 PM, Boris Zbarsky  wrote:

> On 6/18/14, 11:39 AM, Erik Arvidsson wrote:
>
>> This also fits how @@create works for DOM, where the creation of the
>> instance would set up the internal DOM wrapper pointer, never exposing a
>> non initialized DOM object to user code.
>>
>
> Note that in that setup it's impossible to introduce an HTMLElement
> constructor like this:
>
>   var el = new HTMLElement("iframe");
>

This particular one can be done because if the constructor returns an
object that is used instead.

function HTMLElement(tagName = undefined) {
  if (tagName === undefined) throw ...
  var ctor = lookupConstructor(tagName);
  return new ctor;
}


> because the @@create doesn't have the tag name available to create the
> right sort of object...
>

But the constructor is able to return any object it want, basically making
the constructor into a factory method.

This is an ugly pattern so it is discouraged but it does give you some
leeway when you need to support strange things.

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


RE: @@new

2014-06-18 Thread Domenic Denicola
From: Boris Zbarsky [mailto:bzbar...@mit.edu] 

> So this is basically option 2 from
https://mail.mozilla.org/pipermail/es-discuss/2014-June/037849.html if I 
understand right?

Yes, although in this case no initialization checks are necessary, just brand 
checks. Which I guess speaks to your point about how getting this right is 
tricky.

I am not sure there are too many cases where there's an interesting distinction 
between allocated and initialized for the DOM, though. Given how few DOM 
objects have reasonable constructors to begin with, it seems like most of their 
work is being done (conceptually) in [Symbol.create]() anyway.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: @@new

2014-06-18 Thread Allen Wirfs-Brock

On Jun 18, 2014, at 8:39 AM, Erik Arvidsson wrote:

> Another thing to consider is to ensure that @@create initializes all of its 
> slots. For example Date[@@create]() could set its [[DateValue]] to NaN, 
> Map[@@create]() could set its [[MapData]] to an empty list and so on.
> 
> This also fits how @@create works for DOM, where the creation of the instance 
> would set up the internal DOM wrapper pointer, never exposing a non 
> initialized DOM object to user code.

Right, that's the line I'm exploring.  If it can work out @@create are @@new 
more or less the same thing, except for the constructor rewriting.

Allen



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


Re: @@new

2014-06-18 Thread Allen Wirfs-Brock

On Jun 18, 2014, at 8:33 AM, Erik Arvidsson wrote:

> I think the most concerning part of this proposal is that `constructor(...)` 
> gets replaced by `static [Symbol.new](...)` with strange semantics regarding 
> `this`. If we instead had @@new call constructor by default I think most of 
> these concerns go away but then again we are back to two initialization 
> functions and the possibility to observe an object that never went through 
> its constructor.
> 
> 

This is also one of my bigger concerns.  I think the rewriting and 
reinterpretation of what the use wrote as a a constructor may be very 
problematic.   For example,how does this get translated:

class extends C {
  constructor() {
   super();
   super.foo();  //apply the inherited foo method to the new object  
  }
}

If we had a design that didn't require the rewriting of the user provided 
constructor I'd be much more comfortable.  Thinking...more latter...

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


Re: @@new

2014-06-18 Thread Boris Zbarsky

On 6/18/14, 12:09 PM, Domenic Denicola wrote:

From: es-discuss  on behalf of Boris Zbarsky 



While true, I'd like to see a concrete proposal about how we actually proceed 
with making the web platform subclassable in the @@create world.  Whereas in 
the @@new world subclassibility by default is at least somewhat viable...


Hmm, I thought we'd already established how this would work. It's pretty 
seamless with the @@create approach. See:

https://gist.github.com/domenic/3ce8f57a33a25473f508

The "domPointer" stuff is kind of handwavey, but it's still pretty clear how it 
would work.


So this is basically option 2 from 
https://mail.mozilla.org/pipermail/es-discuss/2014-June/037849.html if I 
understand right?


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


Re: @@new

2014-06-18 Thread Boris Zbarsky

On 6/18/14, 11:39 AM, Erik Arvidsson wrote:

This also fits how @@create works for DOM, where the creation of the
instance would set up the internal DOM wrapper pointer, never exposing a
non initialized DOM object to user code.


Note that in that setup it's impossible to introduce an HTMLElement 
constructor like this:


  var el = new HTMLElement("iframe");

because the @@create doesn't have the tag name available to create the 
right sort of object...


This is the flyweight object issue that was mentioned up-thread too: if 
you have to examine your arguments to decide what sort of object to 
create, then @@create is not a viable option.


Whether we need to make this sort of constructor possible is a separate 
issue, of course; for newer specs we're using separate interfaces for 
separate things, so don't need this sort of constructor, I think.


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


Re: @@new

2014-06-18 Thread Jason Orendorff
On Wed, Jun 18, 2014 at 8:55 AM, Domenic Denicola
 wrote:
> What happens if I put [Symbol.new] on a non-function object? Is it now
> constructable? Presumably still not callable though, right?

Yes, it would be constructable but still not callable.

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


Re: @@new

2014-06-18 Thread Kevin Smith
> Another thing to consider is to ensure that @@create initializes all of
> its slots. For example Date[@@create]() could set its [[DateValue]] to NaN,
> Map[@@create]() could set its [[MapData]] to an empty list and so on.
>

I think if you go that route you still may need some checks in place to
ensure that the initializer (constructor) is only executed once.

For instance, you'd never want the Promise constructor to be called twice
on some promise object.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: @@new

2014-06-18 Thread Domenic Denicola
From: es-discuss  on behalf of Boris Zbarsky 


> While true, I'd like to see a concrete proposal about how we actually proceed 
> with making the web platform subclassable in the @@create world.  Whereas in 
> the @@new world subclassibility by default is at least somewhat viable...

Hmm, I thought we'd already established how this would work. It's pretty 
seamless with the @@create approach. See:

https://gist.github.com/domenic/3ce8f57a33a25473f508

The "domPointer" stuff is kind of handwavey, but it's still pretty clear how it 
would work.

---

Following up on Arv's point about the DOM's use of @@create, my understanding 
is that having the two-phase initialization is quite important for the DOM, 
e.g. elements created by the parser will be allocated but never initialized 
(their constructors will never run). You can see this in action today with e.g. 
HTMLImageElement.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: @@new

2014-06-18 Thread Erik Arvidsson
Another thing to consider is to ensure that @@create initializes all of its
slots. For example Date[@@create]() could set its [[DateValue]] to NaN,
Map[@@create]() could set its [[MapData]] to an empty list and so on.

This also fits how @@create works for DOM, where the creation of the
instance would set up the internal DOM wrapper pointer, never exposing a
non initialized DOM object to user code.


On Wed, Jun 18, 2014 at 11:33 AM, Erik Arvidsson 
wrote:

> What about the other direction?
>
> class B {
>   constructor(x) {
> this.x = x;
>   }
>   static [Symbol.create]() {
> var o = super();
> weakMap.set(o, 12345678);  // DOM wrapper foo
> return o;
>   }
> }
>
> function C(x) {
>   B.call(this, x);
> }
> C.__proto__ = B;
> C.prototype = {__proto__: B.prototype};
>
>
> I think the most concerning part of this proposal is that
> `constructor(...)` gets replaced by `static [Symbol.new](...)` with strange
> semantics regarding `this`. If we instead had @@new call constructor by
> default I think most of these concerns go away but then again we are back
> to two initialization functions and the possibility to observe an object
> that never went through its constructor.
>
>
>
> On Tue, Jun 17, 2014 at 8:03 PM, Jason Orendorff <
> jason.orendo...@gmail.com> wrote:
>
>> On Tue, Jun 17, 2014 at 6:55 PM, Erik Arvidsson
>>  wrote:
>> > How does this work with legacy classes?
>> >
>> > function B() {
>> >   this.x = 1;
>> > }
>> > class C extends B {}
>>
>> That works!
>>
>> `new C` desugars to `C[@@new]()`.  C doesn't have a @@new method of
>> its own, so it inherits `Function.prototype[@@new]`.
>>
>> The algorithm for that method is given in the proposal. Step 1 selects
>> the right prototype here (C.prototype), and step 4 calls B as desired.
>>
>> -j
>>
>
>
>
> --
> erik
>



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


Re: @@new

2014-06-18 Thread Erik Arvidsson
What about the other direction?

class B {
  constructor(x) {
this.x = x;
  }
  static [Symbol.create]() {
var o = super();
weakMap.set(o, 12345678);  // DOM wrapper foo
return o;
  }
}

function C(x) {
  B.call(this, x);
}
C.__proto__ = B;
C.prototype = {__proto__: B.prototype};


I think the most concerning part of this proposal is that
`constructor(...)` gets replaced by `static [Symbol.new](...)` with strange
semantics regarding `this`. If we instead had @@new call constructor by
default I think most of these concerns go away but then again we are back
to two initialization functions and the possibility to observe an object
that never went through its constructor.



On Tue, Jun 17, 2014 at 8:03 PM, Jason Orendorff 
wrote:

> On Tue, Jun 17, 2014 at 6:55 PM, Erik Arvidsson
>  wrote:
> > How does this work with legacy classes?
> >
> > function B() {
> >   this.x = 1;
> > }
> > class C extends B {}
>
> That works!
>
> `new C` desugars to `C[@@new]()`.  C doesn't have a @@new method of
> its own, so it inherits `Function.prototype[@@new]`.
>
> The algorithm for that method is given in the proposal. Step 1 selects
> the right prototype here (C.prototype), and step 4 calls B as desired.
>
> -j
>



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


RE: @@new

2014-06-18 Thread Domenic Denicola
What happens if I put [Symbol.new] on a non-function object? Is it now 
constructable? Presumably still not callable though, right?

From: Jason Orendorff
Sent: ‎2014-‎06-‎17 15:22
To: Allen Wirfs-Brock
Cc: EcmaScript; Mark 
Miller
Subject: @@new

Allen asked me to fill out what @@new would mean. Here it is.


## How `new X` works

`new X(...args)`  `X[@@new](...args)`


## How it works for ES5 builtin constructors

`Number(value)` is specified in one section.

`Number[@@new](value)` is specified in another section.

To support subclassing, `Number[@@new]()`, unlike ES5 [1], would set the
new object's prototype to `this.prototype` rather than `Number.prototype`.
Otherwise it all works just like ES5.

The same goes for Object, Array, Function, Date, and the other builtins.


## How it works for regular functions

`Function.prototype[@@new](...arguments)` is called. It works like this:

1.  Let proto = `this.[[Get]]("prototype", this)`.

2.  If proto is not an object, throw a TypeError.

3.  Let obj = ObjectCreate(proto).

4.  If the this value or any object on its prototype chain is an ECMAScript
language function (not a class), then

a.  Let F be that object.

b.  Let result = `F.[[Call]](obj, arguments)`.

c.  If Type(result) is Object then return result.

5.  Return obj.

For regular functions, this behaves exactly like the `[[Construct]]` internal
method in ES5 [2]. Step 4 is there to support regular functions and ES6 classes
that subclass regular functions.


## How it works for ES6 classes

The special `constructor` method in ClassDeclaration/ClassExpression syntax
would desugar to a static @@new method. This class:

class Point {
constructor(x = 0, y = 0) {
this.x = x;
this.y = y;
}
}

would amount to this:

class Point {
static [Symbol.new](x = 0, y = 0) {
var obj = super[Symbol.new]();
obj.x = x;
obj.y = y;
return obj;
}
}

As in the current drafts, ES6 would have to do something mildly fancy (see [3]
and step 8 of [4]) to perform the desugaring.

If a class has no `constructor` method, it inherits the base class's static
@@new method.

The "super Arguments" call syntax in the ES6 drafts would be constrained to
appear only at the top of a constructor, as in Java:

class PowerUp {
constructor(name, price) { ... }
}

class RocketPack extends PowerUp {
constructor() {
super("Rocket Pack", 1000);
this.fuel = FULL_TANK;
}
}

The RocketPack constructor would behave like this:

static [Symbol.new]() {
var obj = super[Symbol.new]("Rocket Pack", 1000);
obj.fuel = FULL_TANK;
return obj;
}

This has different runtime semantics compared the `super()` syntax in the
current ES6 draft, but it serves the same purpose.

And that's all.


## Benefits

*   As with Allen's proposal, we would drop [[Construct]] and the `construct`
trap.

*   Instances of builtin classes are never exposed to scripts before
their internal slots are fully initialized.

*   @@create can be dropped entirely, but we retain the benefit to implementers
that all Maps (for example) can have the same in-memory layout, and other
objects can't become Maps at runtime.

*   Base class constructors are always called.

*   The ES6 draft language in [5] step 5, and many other similar places, would
be backed out. ("If Type(O) is Object and O has a [[NumberData]] internal
slot and the value of [[NumberData]] is undefined, then...")

*   The current ES6 draft specifies new builtin constructors (Map, Set,
WeakMap) to throw a TypeError if called without `new`. This new convention
could be reversed to what ES5 does with Function and Array: `Map()` would
be the same as `new Map()`. User-defined classes could work this way too.
I think developers would appreciate this.

*   These productions would be dropped from the ES6 grammar:

MemberExpression : new super Arguments
NewExpression : new super

If for whatever reason users want these, they can call
`super[Symbol.new]()`. But I think they will no longer be needed.

This would reduce the number of `super` forms to these 3:

super.IdentifierName  // allowed in all methods
super[Expression] // allowed in all methods
super(arguments)  // only allowed in constructors


[1]: http://people.mozilla.org/~jorendorff/es5.1-final.html#sec-15.7.2.1
"ES5 new Number ( [ value ] )"
[2]: http://people.mozilla.org/~jorendorff/es5.1-final.html#sec-13.2.2
"ES5 [[Construct]]"
[3]: 
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-static-semantics-constructormethod
"ES6 Static Semantics: ConstructorMethod"
[4]: 
http://people

RE: @@new

2014-06-18 Thread Domenic Denicola

From: Jason Orendorff
Sent: ‎2014-‎06-‎17 15:22
To: Allen Wirfs-Brock
Cc: EcmaScript; Mark 
Miller
Subject: @@new

Allen asked me to fill out what @@new would mean. Here it is.


## How `new X` works

`new X(...args)`  `X[@@new](...args)`


## How it works for ES5 builtin constructors

`Number(value)` is specified in one section.

`Number[@@new](value)` is specified in another section.

To support subclassing, `Number[@@new]()`, unlike ES5 [1], would set the
new object's prototype to `this.prototype` rather than `Number.prototype`.
Otherwise it all works just like ES5.

The same goes for Object, Array, Function, Date, and the other builtins.


## How it works for regular functions

`Function.prototype[@@new](...arguments)` is called. It works like this:

1.  Let proto = `this.[[Get]]("prototype", this)`.

2.  If proto is not an object, throw a TypeError.

3.  Let obj = ObjectCreate(proto).

4.  If the this value or any object on its prototype chain is an ECMAScript
language function (not a class), then

a.  Let F be that object.

b.  Let result = `F.[[Call]](obj, arguments)`.

c.  If Type(result) is Object then return result.

5.  Return obj.

For regular functions, this behaves exactly like the `[[Construct]]` internal
method in ES5 [2]. Step 4 is there to support regular functions and ES6 classes
that subclass regular functions.


## How it works for ES6 classes

The special `constructor` method in ClassDeclaration/ClassExpression syntax
would desugar to a static @@new method. This class:

class Point {
constructor(x = 0, y = 0) {
this.x = x;
this.y = y;
}
}

would amount to this:

class Point {
static [Symbol.new](x = 0, y = 0) {
var obj = super[Symbol.new]();
obj.x = x;
obj.y = y;
return obj;
}
}

As in the current drafts, ES6 would have to do something mildly fancy (see [3]
and step 8 of [4]) to perform the desugaring.

If a class has no `constructor` method, it inherits the base class's static
@@new method.

The "super Arguments" call syntax in the ES6 drafts would be constrained to
appear only at the top of a constructor, as in Java:

class PowerUp {
constructor(name, price) { ... }
}

class RocketPack extends PowerUp {
constructor() {
super("Rocket Pack", 1000);
this.fuel = FULL_TANK;
}
}

The RocketPack constructor would behave like this:

static [Symbol.new]() {
var obj = super[Symbol.new]("Rocket Pack", 1000);
obj.fuel = FULL_TANK;
return obj;
}

This has different runtime semantics compared the `super()` syntax in the
current ES6 draft, but it serves the same purpose.

And that's all.


## Benefits

*   As with Allen's proposal, we would drop [[Construct]] and the `construct`
trap.

*   Instances of builtin classes are never exposed to scripts before
their internal slots are fully initialized.

*   @@create can be dropped entirely, but we retain the benefit to implementers
that all Maps (for example) can have the same in-memory layout, and other
objects can't become Maps at runtime.

*   Base class constructors are always called.

*   The ES6 draft language in [5] step 5, and many other similar places, would
be backed out. ("If Type(O) is Object and O has a [[NumberData]] internal
slot and the value of [[NumberData]] is undefined, then...")

*   The current ES6 draft specifies new builtin constructors (Map, Set,
WeakMap) to throw a TypeError if called without `new`. This new convention
could be reversed to what ES5 does with Function and Array: `Map()` would
be the same as `new Map()`. User-defined classes could work this way too.
I think developers would appreciate this.

*   These productions would be dropped from the ES6 grammar:

MemberExpression : new super Arguments
NewExpression : new super

If for whatever reason users want these, they can call
`super[Symbol.new]()`. But I think they will no longer be needed.

This would reduce the number of `super` forms to these 3:

super.IdentifierName  // allowed in all methods
super[Expression] // allowed in all methods
super(arguments)  // only allowed in constructors


[1]: http://people.mozilla.org/~jorendorff/es5.1-final.html#sec-15.7.2.1
"ES5 new Number ( [ value ] )"
[2]: http://people.mozilla.org/~jorendorff/es5.1-final.html#sec-13.2.2
"ES5 [[Construct]]"
[3]: 
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-static-semantics-constructormethod
"ES6 Static Semantics: ConstructorMethod"
[4]: 
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-classdefinitionevaluation
"ES6 Runtime Semantics: ClassDefinitionEvalu

Re: @@new

2014-06-18 Thread Boris Zbarsky

On 6/18/14, 3:40 AM, Dmitry Soshnikov wrote:

Personally I think two traps are more intuitive and convenient (and are
present in many other languages: C++, Ruby, etc)


C++ has the sorts of restrictions on calling the superclass constructor 
(have to do it up front, can't skip doing it) that the @@new proposal 
has, no?



and that "parent constructor should always be called"
is a subjective, and just one of the semantics.


While true, I'd like to see a concrete proposal about how we actually 
proceed with making the web platform subclassable in the @@create world. 
 Whereas in the @@new world subclassibility by default is at least 
somewhat viable...


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


Re: @@new

2014-06-18 Thread Andreas Rossberg
On 18 June 2014 09:40, Dmitry Soshnikov  wrote:
> On Tue, Jun 17, 2014 at 12:21 PM, Jason Orendorff
>  wrote:
>> ## Benefits
>>
>> *   As with Allen's proposal, we would drop [[Construct]] and the
>> `construct`
>> trap.
>>
>> *   @@create can be dropped entirely, but we retain the benefit to
>> implementers
>> that all Maps (for example) can have the same in-memory layout, and
>> other
>> objects can't become Maps at runtime.
>
> These are pure implementation details, and only implementation improvements,
> that are not that interesting to actual developers.

The main part of this point is getting rid of @@create, which is far
more than an implementation detail. If we can actually pull this off
-- in particular, getting rid of the ability to observe
half-constructed objects -- then I'd +100 it. It's still worth trying,
but as David points out, it's not so easy.

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


Re: Standard builtins' prototypes and toString

2014-06-18 Thread Till Schneidereit
On Tue, Jun 17, 2014 at 11:27 PM, Allen Wirfs-Brock 
wrote:

>
> On Jun 17, 2014, at 1:41 PM, Till Schneidereit wrote:
>
> On Tue, Jun 17, 2014 at 6:07 PM, Mark Miller  wrote:
>
>> I am happy with #b as well, though I prefer #c. I also agree with C.
>> Scott's interpretation of #c, to mean, appropriate degenerate value, which
>> is generally the zero value, but is plausibly NaN for Date.
>>
>> Whichever experiment Nightly tries first with a positive outcome, I
>> expect that's what we'll do, since the difference between #b and #c is not
>> large enough to be worth waiting for a second experiment.
>>
>
> I don't much care which one we choose, to be honest. I kinda doubt that #b
> will have more compatibility issues than #c[1], and find conceptually
> cleaner by a thin margin: a non-Date object isn't an invalid Date, it's not
> a Date. But then again, if you don't want an object to be treated as a
> Date, don't call Date's toString on it? Implementation-wise, it's pretty
> much a wash, at least.
>
>
> I think the most important thing to test is changing Date.prototype to be
> a non-date (and for that matter changing all the other legacy built-ins
> that have changed to non-instances). That's the big bet and we should get
> feedback on.
>

Agreed.


>
> As far as I can tell, toString being an issue is just a conjecture that
> hasn't been tested. So, you could even go ahead an implement the
> corresponding toString methods as currently stands in the ES6 spec. (throw
> for the wrong kind of object) which probably requires no change to their
> current implementation.
>

I'm somewhat opposed to this for two reasons:

One is that I'm pretty sure that it won't be compatible, whereas I'm
optimistic about making Date.prototype a non-Date. There are tens of
thousands of people using Nightly as their default browser, and while that
makes it a good first target for experiments like this, it also means that
we shouldn't do experiments where we're not optimistic about the outcome.

The other is that I still think the standard library shouldn't contain
objects that throw when they're string-ified or value-ified.


>
> If we run into an actual toString issue we will have a better idea of
> which fix may be preferable.
>

How is that? The script-visible differences between #b and #c would mostly
be that Date.prototype.toString would return "[Object Date]" for #b and (as
it does now) "Invalid Date" for #c. It's not clear to me how testing the
spec status quo would give us any more information about which one of these
would be more compatible or preferable on other grounds.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: @@new

2014-06-18 Thread Dmitry Soshnikov
On Tue, Jun 17, 2014 at 12:21 PM, Jason Orendorff  wrote:
...

>
> ## Benefits
>
> *   As with Allen's proposal, we would drop [[Construct]] and the
> `construct`
> trap.
>
> *   @@create can be dropped entirely, but we retain the benefit to
> implementers
> that all Maps (for example) can have the same in-memory layout, and
> other
> objects can't become Maps at runtime.
>
>
These are pure implementation details, and only implementation
improvements, that are not that interesting to actual developers.



>
> This would reduce the number of `super` forms to these 3:
>
> super.IdentifierName  // allowed in all methods
> super[Expression] // allowed in all methods
> super(arguments)  // only allowed in constructors
>
>
I missed that: so we got another restriction, and devs won't be able to use
convenient concise `super()` calls from other methods? I don't think it's
the best direction.

Overall, we got three restrictions:

  (1) super only on top of the constructor,
  (2) want it or not: parent constructor is always called,
  (3) you can't use concise super calls from methods.
  + bonus (4) you have to use some verbose syntax of static [Symbol.new]()
{} to do needed hacks.

What all these for? To exclude [[Construct]]/@@create form the
implementation? But developers are not interested in the implementation.
Developers want to make convenient super-calls, do not call parent
constructors if it's not needed (yes, it's rare, but can be), or to call it
whenever they want after predefined prologue.

Personally I think two traps are more intuitive and convenient (and are
present in many other languages: C++, Ruby, etc) than this
"spec/implementation-optimization", and users would appreciate the `new`
and `constructor` traps. The former can be used in rare cases when they'll
need custom allocation (and `this` value is not available there yet), and
the `constructor` is a normal initialiser of the allocated instance.

I mean, there should be a very strong reason to change an intuitive
semantics to this approach. "Spec/implementation optimizations" is not the
best reason, and that "parent constructor should always be called" is a
subjective, and just one of the semantics.

P.S.: as for the libraries, some "libraries" (actually my tests) were also
coupled to this allocate/initialize pair hooks approach:
https://gist.github.com/DmitrySoshnikov/1367025#file-r-proto-class-class-js-L23-L41

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