Re: this value inside anonymous generator

2015-03-30 Thread Jordan Harband
Can you not just use .bind here?

```
spawn(function* () {
  let data = yield this.fetchData();
}.bind(this));
```

On Mon, Mar 30, 2015 at 11:38 PM, Niloy Mondal 
wrote:

> I wrote some code like the following in tracuer
>
> ```
> class Foo {
>   constructor() {
> spawn(function*() {
>   let data = yield this.fetchData(); // error because 'this' is
> undefined
> });
>   }
>
>   fetchData() {
> // returns promise
>   }
> }
> ```
>
> I used the spawn function from here:
> https://gist.github.com/jakearchibald/31b89cba627924972ad6
>
> The code doesn't work because 'this' is undefined. I can fix it by using
> 'let that = this' pattern. But it feels like a step backward now that I've
> fallen in love with lambda functions. So I was wondering if it would be
> possible to use lexical binding for 'this' inside anonymous generators.
>
> ___
> 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


this value inside anonymous generator

2015-03-30 Thread Niloy Mondal
I wrote some code like the following in tracuer

```
class Foo {
  constructor() {
spawn(function*() {
  let data = yield this.fetchData(); // error because 'this' is
undefined
});
  }

  fetchData() {
// returns promise
  }
}
```

I used the spawn function from here:
https://gist.github.com/jakearchibald/31b89cba627924972ad6

The code doesn't work because 'this' is undefined. I can fix it by using
'let that = this' pattern. But it feels like a step backward now that I've
fallen in love with lambda functions. So I was wondering if it would be
possible to use lexical binding for 'this' inside anonymous generators.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Determine if a value is Callable/Constructible

2015-03-30 Thread Peter Flannery
I personally think it's better to have **harmony** between ES5 and ES6
classes and not incompatibility.
The web and the like are currently littered with applications that use
[[call]] as a sub classing technique and now all these apps will be
give a harsh choice, either disregard using ES6 class syntax,
completely overhaul to suit ES6 or just don't move to ES6 until
time\money budgets permit.

Is it not possible to:

1. Have a unified construct for both class and function syntax, i.e.
`SomeClass.constructor.call` can be used to sub class for both ES6 and
ES6
2. Instead of throwing the message `Class constructors cannot be
invoked without 'new'` **change it to become** `Class constructors
cannot be invoked without using 'new' or it's .constructor method`
3. Functions will continue to have [[call]] regardless but it should
still be recommended to use `SomeClass.constructor.call` for sub
classing for great compatibility
4. Polyfill vendors have their own spec for this scenario. i.e. when
the detect class syntax is used then mark the output ES5 prototype
with a [[class-tag]] that allows them to assert and throw the same
`Class constructors cannot be invoked.` message as stated in point
2 above
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: `of` operator ES7 proposal from Ian Bicking

2015-03-30 Thread Brendan Eich

Frankie Bagnardi wrote:


First, you shouldn’t assume this would be based on the
Symbol.iterator protocol.

Would |Object.create(null, {[Symbol.iterator]: value: ...})| work as 
it does in for..of?




No, as with instanceof and @@hasInstance in general, you wouldn't get 
membership test for free.


But unlike instanceof, you wouldn't get common case behavior for free 
either, so that's the downside. You'd have to provide a value such as 
Array#includes for the property named by Symbol.hasElement (or whatever 
the best name analogous to @@hasInstance is).


It seems like the main problem would be infinite sequences. That means 
either infinite loops (ugh), or the language/user setting an arbitrary 
number of max values to check (ew).




Neither.

If I do have an arbitrary iterable, I need to easily create something 
I can pass to for..of with |if (x of fn(xs))| where fn is provided by 
ecmascript.




You'd need to implement a separate MOP hook, let's call it @@hasElement 
for now.


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


Re: `of` operator ES7 proposal from Ian Bicking

2015-03-30 Thread Brendan Eich
There's no problem making `of` contextual provided you use a restricted 
production:


RelationalExpression :
RelationalExpression [no LineTerminator here] |of| ShiftExpression _

See 
http://wiki.ecmascript.org/doku.php?id=harmony:egal#is_and_isnt_operators where 
we noticed that restricted productions allow the contextual use of new 
keyword-operators without breaking backward compatibility.


/be


Bergi wrote:

Brendan Eich schrieb:

 From https://plus.google.com/+IanBicking/posts/PbXDtNF9Gg6:

Huh, "for (attr in obj)" goes along with "if (attr in obj)", but "for
(item of array)" doesn't have an equivalent "if (item of array)"

It's obvious in hindsight. An `of` operator …


I would like such an operator as well, but I can see a big problem 
with this proposal: "of" is not a reserved keyword.
And it certainly has its usage as an identifier name already, most 
prominently: Array.of.
The fantasyland applicatives 
 do have such 
a method as well. I found a few uses of it in github code 
 
(most of those thousands are false positives or a particular test 
case, this example 
 
is not).


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


Re: `of` operator ES7 proposal from Ian Bicking

2015-03-30 Thread Bergi

Brendan Eich schrieb:

 From https://plus.google.com/+IanBicking/posts/PbXDtNF9Gg6:

Huh, "for (attr in obj)" goes along with "if (attr in obj)", but "for
(item of array)" doesn't have an equivalent "if (item of array)"

It's obvious in hindsight. An `of` operator …


I would like such an operator as well, but I can see a big problem with 
this proposal: "of" is not a reserved keyword.
And it certainly has its usage as an identifier name already, most 
prominently: Array.of.
The fantasyland applicatives 
 do have such a 
method as well. I found a few uses of it in github code 
 
(most of those thousands are false positives or a particular test case, 
this example 
 
is not).


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


Re: `of` operator ES7 proposal from Ian Bicking

2015-03-30 Thread Frankie Bagnardi
First, you shouldn’t assume this would be based on the Symbol.iterator
protocol.

Would Object.create(null, {[Symbol.iterator]: value: ...}) work as it does
in for..of?

It seems like the main problem would be infinite sequences. That means
either infinite loops (ugh), or the language/user setting an arbitrary
number of max values to check (ew).

If I do have an arbitrary iterable, I need to easily create something I can
pass to for..of with if (x of fn(xs)) where fn is provided by ecmascript.
​


On Mon, Mar 30, 2015 at 12:02 PM, Brendan Eich  wrote:

> Michał Wadas wrote:
>
>> First possible problem - "of" used in if statement can put iterator in
>> unexpected state or result in arbitrary side effects.
>>
>
> What iterator?
>
> First, you shouldn't assume this would be based on the Symbol.iterator
> protocol. I wrote something like @@hasInstance for instanceof was the
> precedent to follow.
>
> Second, the iteration protocol would require exhaustively searching for
> values. Side effects of iteration are the least worry!
>
> Finally, even if the iteration protocol were used, there would be no
> shared/reused iterator. You get a fresh one from well-implemented iterables.
>
>
> /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: `of` operator ES7 proposal from Ian Bicking

2015-03-30 Thread Brendan Eich

Michał Wadas wrote:
First possible problem - "of" used in if statement can put iterator in 
unexpected state or result in arbitrary side effects.


What iterator?

First, you shouldn't assume this would be based on the Symbol.iterator 
protocol. I wrote something like @@hasInstance for instanceof was the 
precedent to follow.


Second, the iteration protocol would require exhaustively searching for 
values. Side effects of iteration are the least worry!


Finally, even if the iteration protocol were used, there would be no 
shared/reused iterator. You get a fresh one from well-implemented iterables.


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


Re: `of` operator ES7 proposal from Ian Bicking

2015-03-30 Thread Brendan Eich

Axel Rauschmayer wrote:
* Name-wise, is `has` a possibility? It feels more intuitive and I 
don’t think the duality with `in` matters (given that `for-in` will 
probably rarely be used in the future, due to `for-of` and `Map`).


You don't want `has` for two reasons: it un-transposes operands back to 
receiver has value, which is almost as long as, and less worth a special 
form than, receiver.has(value) -- but that walks back into the has vs. 
include perplex.


Second reason: the parallel is in : for-in :: of : for-of. That's why 
the value goes on the left of the *operator*, the object (in method call 
terms, receiver) on the right.


* Will it ever be possible to define arbitrary infix operators? If 
yes, should this operator wait until that feature is available?


Again we don't wait for macros before adding syntax. Takes too long, 
multiples risk, starves users of affordances.


People who know more about such things (dherman!) caution against ever 
getting sweet.js support into the browser-staged runtimes. It's an AOT tool.


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


Making class constructors work on preallocated objects

2015-03-30 Thread Claude Pache
Hi,

As you know, as specified in ES6 (or should I say ES 2015?), constructors 
defined through the `class` construct cannot be invoked with a preallocated 
object, i.e., invoked as `Foo.call(obj)` instead of `obj = new Foo`.

I have reflected on how to make that just work, but without failing silently 
on, e.g., builtins. Here are the result of my thoughts:

https://gist.github.com/claudepache/ca20472f050443644f29

Basically, constructors (ES functions with a [[Construct]] internal slot) are 
distinguished between those that can be invoked on a preallocated object (e.g., 
`function foo(baz) { this.bar = baz }`) and those that cannot (e.g., the `Map` 
builtin). Then, the semantics of `super()` inside class constructors is 
carefully reviewed in order to just work for class constructors invoked as 
`Foo.call(obj)`, and to protest when attempting to do impossible things with, 
e.g., `Map` or `Array`.

―Claude


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


Re: Determine if a value is Callable/Constructible

2015-03-30 Thread Boris Zbarsky

On 3/30/15 1:33 PM, Axel Rauschmayer wrote:

As in “makes sense to call”. In the past, `typeof x === 'function'” was
an adequate test for checking whether it makes sense to call `x`.


Except for all the DOM constructors, right?

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


Re: Determine if a value is Callable/Constructible

2015-03-30 Thread Kevin Smith
>
>
> That distinction means that you can’t “really” [[Call]] a constructor,
> it’s just that the reason is slightly different from trying to [[Call]] an
> Array instance (or something)
>

Another way to look at the situation is that, by default, calling a class
constructor will throw an error.  That default may be changed however.
Just not with ES6 : )
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Determine if a value is Callable/Constructible

2015-03-30 Thread Domenic Denicola
> It could still be identified as a “function” for compat with ES5, but the
> behaviour is different from any other sort of function, it should be
> identifiable as different.

Right, but again, I don't think the behavior is any different from `function 
f() { throw new TypeError(); }`, so whatever the test you write returns for 
classes, my position is that it should return the same thing for `f`.

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


Re: Determine if a value is Callable/Constructible

2015-03-30 Thread Caitlin Potter
I think we’re on the same page that the runtime is the one doing the throwing, 
but that doesn’t really matter. The point is, if you can’t actually invoke the 
authored code, you can’t really call the authored code “call-able”. To the VM, 
the difference doesn’t matter a whole lot, but to human beings, it does. It’s 
disingenuous to call it “call-able” if the authored code can’t be “called”. (A 
proxy trap doesn’t really make it “callable” either, it just allows different 
code to be “called” in its place).

It could still be identified as a “function” for compat with ES5, but the 
behaviour is different from any other sort of function, it should be 
identifiable as different.

> On Mar 30, 2015, at 1:54 PM, Domenic Denicola  wrote:
> 
> The distinction you're really pointing to here is the distinction between 
> user-generated throwing functions and runtime-generated ones. Both are 
> called. User-generated ones you could edit the source code of and insert a 
> `called = true` line first, whereas runtime-generated ones you could not. But 
> that's not a real material difference in call-ability.
> 

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


RE: Determine if a value is Callable/Constructible

2015-03-30 Thread Domenic Denicola
The distinction you're really pointing to here is the distinction between 
user-generated throwing functions and runtime-generated ones. Both are called. 
User-generated ones you could edit the source code of and insert a `called = 
true` line first, whereas runtime-generated ones you could not. But that's not 
a real material difference in call-ability.

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


Re: Determine if a value is Callable/Constructible

2015-03-30 Thread Caitlin Potter
>On Mar 30, 2015, at 1:44 PM, Domenic Denicola  wrote:
>>From: Axel Rauschmayer [mailto:a...@rauschma.de] 
>>As in “makes sense to call”. In the past, `typeof x === 'function'” was an 
>>adequate test for checking whether it makes sense to call `x`.
>
I> tried to explain explicitly why I don't think this is true.
>
>>Since ES6, it isn’t, anymore.
>
>I disagree. The situation has not changed at all.

As I said above:

```js
var called = false;
function F() {
  called = true;
  throw new TypeError(“can’t call F()”);
}

F(); // Throws, but `called` is true

called = false;
class C {
  constructor() {
called = true;
throw new TypeError(“can’t call C()”);
  }
}

C(); // Throws, but `called` is false, because the constructor was never invoked
```

That distinction means that you can’t “really” [[Call]] a constructor, it’s 
just that the reason is slightly different from trying to [[Call]] an Array 
instance (or something)
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Determine if a value is Callable/Constructible

2015-03-30 Thread Domenic Denicola
From: Axel Rauschmayer [mailto:a...@rauschma.de] 

> As in “makes sense to call”. In the past, `typeof x === 'function'” was an 
> adequate test for checking whether it makes sense to call `x`.

I tried to explain explicitly why I don't think this is true.

> Since ES6, it isn’t, anymore.

I disagree. The situation has not changed at all.

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


Re: Determine if a value is Callable/Constructible

2015-03-30 Thread Axel Rauschmayer
>> In some way, that would even be correct – depending on what you expect a 
>> function to be: something callable or something constructible. Alas, there 
>> is currently no simple way to distinguish “callable” and “constructible”.
> 
> Why do you say they're not callable?


As in “makes sense to call”. In the past, `typeof x === 'function'” was an 
adequate test for checking whether it makes sense to call `x`. Since ES6, it 
isn’t, anymore. That’s why the checks proposed by Caitlin will be nice to have.

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



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


Re: Determine if a value is Callable/Constructible

2015-03-30 Thread Caitlin Potter
>On Mar 30, 2015, at 12:20 PM, Domenic Denicola  wrote:
>
>Why do you say they're not callable?
>
>Is this function callable?
>
>   function f() {
> throw new TypeError(“f immediately throws");
>   }

I think there’s a distinction here.

`function f() {}` might throw when called, but that’s in the author of the 
function’s control.

`class C {}` will always throw when called (in the current draft), so you can’t 
“really” consider it callable. No user-authored code is invoked when 
[[Call]]-ing a class constructor___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Determine if a value is Callable/Constructible

2015-03-30 Thread Caitlin Potter
>Unfortunately, we can't use a magic method name.  Just to throw out a couple 
>of other ideas though: 

>Contextual keyword after constructor:
>
>class C {
>  constructor() { /* new me */ }
>  constructor call() { /* call me */ }
>}

This one looks like the most readable — I would make a slight adjustment:

class C {
  constructor() { /* new me *. }
  call constructor() { /* call me */ }
}

(just for the purpose of readability)

I think it might be hard to mix this up with computed property names, so `call 
[‘constructor’]()` might be a no-go? same with `[‘constructor’] call()` tbh

> On Mar 30, 2015, at 12:20 PM, Kevin Smith  wrote:
> 
> I like the idea of a special syntactic form a lot. One of the nice things 
> about `constructor` is that it's easy to explain "you [[Construct]] with the 
> constructor". We can't use `call` similarly any more, but I totally agree 
> something like it would be pretty nice.
> 
> Unfortunately, we can't use a magic method name.  Just to throw out a couple 
> of other ideas though: 
> 
> Parens sans method name:
> 
> class C {
>   constructor() { /* new me */ }
>   () { /* call me */ }
> }
> 
> Contextual keyword after constructor:
> 
> class C {
>   constructor() { /* new me */ }
>   constructor call() { /* call me */ }
> }
> 
> With a "dot" instead:
> 
> class C {
>   constructor() { /* new me */ }
>   constructor.call() { /* call me */ }
> }
> 
> 

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


RE: Determine if a value is Callable/Constructible

2015-03-30 Thread Domenic Denicola
From: Axel Rauschmayer [mailto:a...@rauschma.de] 

> In some way, that would even be correct – depending on what you expect a 
> function to be: something callable or something constructible. Alas, there is 
> currently no simple way to distinguish “callable” and “constructible”.

Why do you say they're not callable?

Is this function callable?

function f() {
  throw new TypeError("cannot call f because you're not pretty enough");
}

what about


function f() {
  throw new TypeError("Class constructors cannot be invoked without 'new'");
}

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


Re: Determine if a value is Callable/Constructible

2015-03-30 Thread Kevin Smith
>
> I like the idea of a special syntactic form a lot. One of the nice things
> about `constructor` is that it's easy to explain "you [[Construct]] with
> the constructor". We can't use `call` similarly any more, but I totally
> agree something like it would be pretty nice.
>

Unfortunately, we can't use a magic method name.  Just to throw out a
couple of other ideas though:

Parens sans method name:

class C {
  constructor() { /* new me */ }
  () { /* call me */ }
}

Contextual keyword after constructor:

class C {
  constructor() { /* new me */ }
  constructor call() { /* call me */ }
}

With a "dot" instead:

class C {
  constructor() { /* new me */ }
  constructor.call() { /* call me */ }
}
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Determine if a value is Callable/Constructible

2015-03-30 Thread Axel Rauschmayer
> If you made them non-callable by not implementing [[Call]], then typeof would 
> no longer return "function", which would be ... O_o.

In some way, that would even be correct – depending on what you expect a 
function to be: something callable or something constructible. Alas, there is 
currently no simple way to distinguish “callable” and “constructible”.

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



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


Re: Determine if a value is Callable/Constructible

2015-03-30 Thread Yehuda Katz
On Mon, Mar 30, 2015 at 8:54 AM, Domenic Denicola  wrote:

> From: Kevin Smith [mailto:zenpars...@gmail.com]
>
> > I'd imagine that you'd re-spec [[Call]] for class constructors to
> basically do `this[Symbol.call](...args)` instead of just throw.  It would
> therefore only have an effect within class constructors.  Is that still
> weird?
>
> At least it's explicable, but it's still pretty weird I think. I mean, we
> don't specify [[Construct]] by saying that it does `new
> this.prototype.constructor(...args)` or similar. The asymmetry is jarring.
>
> And it's weird to have this symbol with such a generic name that doesn't
> work for anything except class syntax. I'd expect symbols to be for
> re-usable protocols... that's fuzzy intuition though, I admit, and might be
> contradicted by existing examples.
>

I like the idea of a special syntactic form a lot. One of the nice things
about `constructor` is that it's easy to explain "you [[Construct]] with
the constructor". We can't use `call` similarly any more, but I totally
agree something like it would be pretty nice.

On the flip side, it's not *entirely* clear that allowing people to
override [[Call]] on an existing function is a no-go. Changing the `typeof`
via installing a symbol definitely seems like bad juju though.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Determine if a value is Callable/Constructible

2015-03-30 Thread Domenic Denicola
From: Kevin Smith [mailto:zenpars...@gmail.com] 

> I'd imagine that you'd re-spec [[Call]] for class constructors to basically 
> do `this[Symbol.call](...args)` instead of just throw.  It would therefore 
> only have an effect within class constructors.  Is that still weird?

At least it's explicable, but it's still pretty weird I think. I mean, we don't 
specify [[Construct]] by saying that it does `new 
this.prototype.constructor(...args)` or similar. The asymmetry is jarring.

And it's weird to have this symbol with such a generic name that doesn't work 
for anything except class syntax. I'd expect symbols to be for re-usable 
protocols... that's fuzzy intuition though, I admit, and might be contradicted 
by existing examples.

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


Re: Determine if a value is Callable/Constructible

2015-03-30 Thread Yehuda Katz
Yehuda Katz
(ph) 718.877.1325

On Mon, Mar 30, 2015 at 8:09 AM, Domenic Denicola  wrote:

> I don’t think [Symbol.call] is a very good mechanism. A new syntactic form
> would make more sense.
>
> It doesn’t seem right that you should have to introduce an observable
> prototype property just to get [[Call]] behavior. (Or a constructor
> property, if you change the syntax to `static [Symbol.call]() { … }`.)
>

A new syntactic form sounds good to me :)


>
> And it raises the question of what happens when I add a [Symbol.call]
> property to other objects. What does it even mean? If I do `var obj = {
> prototype: { [Symbol.call]() { console.log("foo"); } } }`, can I now call
> `obj()`? Is `typeof obj === "function"`? Very strange stuff. Presumably not
> very VM-friendly either, but that's just a guess.
>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Determine if a value is Callable/Constructible

2015-03-30 Thread Kevin Smith
>
> It doesn’t seem right that you should have to introduce an observable
> prototype property just to get [[Call]] behavior. (Or a constructor
> property, if you change the syntax to `static [Symbol.call]() { … }`.)
>
> And it raises the question of what happens when I add a [Symbol.call]
> property to other objects. What does it even mean? If I do `var obj = {
> prototype: { [Symbol.call]() { console.log("foo"); } } }`, can I now call
> `obj()`? Is `typeof obj === "function"`? Very strange stuff. Presumably not
> very VM-friendly either, but that's just a guess.
>

I'd imagine that you'd re-spec [[Call]] for class constructors to basically
do `this[Symbol.call](...args)` instead of just throw.  It would therefore
only have an effect within class constructors.  Is that still weird?

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


Re: Determine if a value is Callable/Constructible

2015-03-30 Thread Caitlin Potter

> If you made them non-callable by not implementing [[Call]], then typeof would 
> no longer return "function", which would be ... O_o.


s/Object (implements [[Call]]) |“function” /Object (implements [[Call]] 
or [[FunctionKind]] is classConstructor) |  “function”/g

Problem solved!

I jest — but making a constructor identifiable as a function while still noting 
that it’s not “really” callable is certainly possible


> On Mar 30, 2015, at 11:27 AM, Domenic Denicola  wrote:
> 
> If you made them non-callable by not implementing [[Call]], then typeof would 
> no longer return "function", which would be ... O_o.
> 
>> -Original Message-
>> From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of
>> Caitlin Potter
>> Sent: Monday, March 30, 2015 11:25
>> To: Yehuda Katz
>> Cc: es-discuss@mozilla.org
>> Subject: Re: Determine if a value is Callable/Constructible
>> 
 But in either case, these (IsCallable / IsConstructor) are pretty basic
>> qualities of objects that a Reflection* api ought to be able to read into, 
>> imho.
>>> 
>>> What Allen is saying is that the implementation of "throw if
>>> constructor" doesn't work by not implementing [[Call]], but rather by
>> implementing [[Call]] to throw, so those reflective APIs would say the wrong
>> thing, and that this is observable via proxies.
>> 
>> It’s a fair point, constructors do have a [[Call]] internal method — there’s 
>> no
>> reason this needs to be described this way though. Instead of the extra step
>> for classConstructors in 9.2.1, class constructors could just as easily not 
>> have a
>> [[Call]] method at all (by default). I guess what I’m getting at is, right 
>> now
>> they aren’t “really” callable, it’s just that the way their 
>> non-callable-ness is
>> expressed makes them appear callable (which probably should not be the
>> case). Since they’re intrinsically not callable (currently), they shouldn’t 
>> be
>> treated as callable.
>> 
>> What Domenic is saying later on makes sense, the magic “call-code” method
>> (should it ever exist) shouldn’t be a property of the class prototype, so a
>> special syntactic form would work better (but also be kind of awful, too).
>> 
>>> 
>>> Allen, can you say more about why you spec'ed it that way?
>>> 
>>> 
 
 
> On Mar 29, 2015, at 11:51 PM, Caitlin Potter 
>> wrote:
> 
> ...
> 
> Reflect.isConstructor(fn) -> true if Class constructor, generator,
> or legacy (and non-builtin) function syntactic form
> Reflect.isCallable(fn) -> true for pretty much any function, except
> for class constructors and a few builtins
 
 I’ve already seen another situation (node’s Buffer) where code could be
>> simplified by using a ES6 class definition but where that is prevented 
>> because
>> a class constructor throws when called.
 
 Just to clarify something.  Class constructors actually are “callable”.  
 You
>> can observe this by the fact that Proxy allows you to install an “apply” 
>> handler
>> (the reification of the [[[Call]] internal method) on a class constructor.   
>> The
>> the fact that an object can be [[Call]]’ed is already reflected  by the 
>> typeof
>> operator.  Class constructors throw when called because at the last minute
>> we choose to make their [[Call]] do an explicit throw not because they aren’t
>> callable.
 
 There is no intrinsic reason why we needed to mandate that class
>> constructors should throw when called.  We even provided a simple and
>> straight forward way (new.target===undefined) that a ES constructor body
>> can use to determine whether it was called or new’ed.
 
 I think we should just drop that throws when called feature of class
>> constructors..
 
 (The restriction was added to future proof for the possibility of
 inventing some other way to provide a class with distinct new/call
 behavior. I don’t think we need nor can afford to wait for the
 invention of a new mechanism which will inevitably be more complex
 than new.target, which we already have.)
 
 Allen
 
 
>>> 
>>> ___
>>> 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: Determine if a value is Callable/Constructible

2015-03-30 Thread Domenic Denicola
If you made them non-callable by not implementing [[Call]], then typeof would 
no longer return "function", which would be ... O_o.

> -Original Message-
> From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of
> Caitlin Potter
> Sent: Monday, March 30, 2015 11:25
> To: Yehuda Katz
> Cc: es-discuss@mozilla.org
> Subject: Re: Determine if a value is Callable/Constructible
> 
> >>But in either case, these (IsCallable / IsConstructor) are pretty basic
> qualities of objects that a Reflection* api ought to be able to read into, 
> imho.
> >
> >What Allen is saying is that the implementation of "throw if
> >constructor" doesn't work by not implementing [[Call]], but rather by
> implementing [[Call]] to throw, so those reflective APIs would say the wrong
> thing, and that this is observable via proxies.
> 
> It’s a fair point, constructors do have a [[Call]] internal method — there’s 
> no
> reason this needs to be described this way though. Instead of the extra step
> for classConstructors in 9.2.1, class constructors could just as easily not 
> have a
> [[Call]] method at all (by default). I guess what I’m getting at is, right now
> they aren’t “really” callable, it’s just that the way their non-callable-ness 
> is
> expressed makes them appear callable (which probably should not be the
> case). Since they’re intrinsically not callable (currently), they shouldn’t be
> treated as callable.
> 
> What Domenic is saying later on makes sense, the magic “call-code” method
> (should it ever exist) shouldn’t be a property of the class prototype, so a
> special syntactic form would work better (but also be kind of awful, too).
> 
> >
> > Allen, can you say more about why you spec'ed it that way?
> >
> >
> > >
> > >
> > >> On Mar 29, 2015, at 11:51 PM, Caitlin Potter 
> wrote:
> > >>
> > >> ...
> > >>
> > >> Reflect.isConstructor(fn) -> true if Class constructor, generator,
> > >> or legacy (and non-builtin) function syntactic form
> > >> Reflect.isCallable(fn) -> true for pretty much any function, except
> > >> for class constructors and a few builtins
> > >
> > > I’ve already seen another situation (node’s Buffer) where code could be
> simplified by using a ES6 class definition but where that is prevented because
> a class constructor throws when called.
> > >
> > > Just to clarify something.  Class constructors actually are “callable”.  
> > > You
> can observe this by the fact that Proxy allows you to install an “apply” 
> handler
> (the reification of the [[[Call]] internal method) on a class constructor.   
> The
> the fact that an object can be [[Call]]’ed is already reflected  by the typeof
> operator.  Class constructors throw when called because at the last minute
> we choose to make their [[Call]] do an explicit throw not because they aren’t
> callable.
> > >
> > > There is no intrinsic reason why we needed to mandate that class
> constructors should throw when called.  We even provided a simple and
> straight forward way (new.target===undefined) that a ES constructor body
> can use to determine whether it was called or new’ed.
> > >
> > > I think we should just drop that throws when called feature of class
> constructors..
> > >
> > > (The restriction was added to future proof for the possibility of
> > > inventing some other way to provide a class with distinct new/call
> > > behavior. I don’t think we need nor can afford to wait for the
> > > invention of a new mechanism which will inevitably be more complex
> > > than new.target, which we already have.)
> > >
> > > Allen
> > >
> > >
> >
> > ___
> > 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: Determine if a value is Callable/Constructible

2015-03-30 Thread Caitlin Potter
>>But in either case, these (IsCallable / IsConstructor) are pretty basic 
>>qualities of objects that a Reflection* api ought to be able to read into, 
>>imho.
>
>What Allen is saying is that the implementation of "throw if constructor" 
>doesn't work by not implementing [[Call]], but rather by implementing [[Call]] 
>to
>throw, so those reflective APIs would say the wrong thing, and that this is 
>observable via proxies.

It’s a fair point, constructors do have a [[Call]] internal method — there’s no 
reason this needs to be described this way though. Instead of the extra step 
for classConstructors in 9.2.1, class constructors could just as easily not 
have a [[Call]] method at all (by default). I guess what I’m getting at is, 
right now they aren’t “really” callable, it’s just that the way their 
non-callable-ness is expressed makes them appear callable (which probably 
should not be the case). Since they’re intrinsically not callable (currently), 
they shouldn’t be treated as callable.

What Domenic is saying later on makes sense, the magic “call-code” method 
(should it ever exist) shouldn’t be a property of the class prototype, so a 
special syntactic form would work better (but also be kind of awful, too).

> 
> Allen, can you say more about why you spec'ed it that way?
>  
> 
> >
> >
> >> On Mar 29, 2015, at 11:51 PM, Caitlin Potter  
> >> wrote:
> >>
> >> ...
> >>
> >> Reflect.isConstructor(fn) -> true if Class constructor, generator, or 
> >> legacy (and non-builtin) function syntactic form
> >> Reflect.isCallable(fn) -> true for pretty much any function, except for 
> >> class constructors and a few builtins
> >
> > I’ve already seen another situation (node’s Buffer) where code could be 
> > simplified by using a ES6 class definition but where that is prevented 
> > because a class constructor throws when called.
> >
> > Just to clarify something.  Class constructors actually are “callable”.  
> > You can observe this by the fact that Proxy allows you to install an 
> > “apply” handler (the reification of the [[[Call]] internal method) on a 
> > class constructor.   The the fact that an object can be [[Call]]’ed is 
> > already reflected  by the typeof operator.  Class constructors throw when 
> > called because at the last minute we choose to make their [[Call]] do an 
> > explicit throw not because they aren’t callable.
> >
> > There is no intrinsic reason why we needed to mandate that class 
> > constructors should throw when called.  We even provided a simple and 
> > straight forward way (new.target===undefined) that a ES constructor body 
> > can use to determine whether it was called or new’ed.
> >
> > I think we should just drop that throws when called feature of class 
> > constructors..
> >
> > (The restriction was added to future proof for the possibility of inventing 
> > some other way to provide a class with distinct new/call behavior. I don’t 
> > think we need nor can afford to wait for the invention of a new mechanism 
> > which will inevitably be more complex than new.target, which we already 
> > have.)
> >
> > Allen
> >
> >
> 
> ___
> 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: Determine if a value is Callable/Constructible

2015-03-30 Thread Domenic Denicola
Great to get the ball rolling. Here's some issues I'd bring up at the meeting, 
so we can get a head start:

- As discussed recently in 
https://esdiscuss.org/topic/reflect-getownpropertysymbols, right now Reflect 
only holds counterparts to the proxy traps. I think this is kind of a nice 
property. Do we want to expand Reflect into a dumping ground for all 
"reflective" operations? That's been implied many times on the list, but so far 
hasn't happened, from what I can see. On the other hand, I don't have any good 
ideas for where else to put these things. (Maybe Function.isConstructor? Not 
sure it scales.)

- Reflect.isCallable seems pretty pointless, when you can just do `typeof x === 
"function"`. YAGNI IMO. Note that it also doesn't match your earlier 
description from 
https://esdiscuss.org/topic/determine-if-a-value-is-callable-constructible#content-0,
 so it presumably doesn't solve those use cases. (But that definition can't 
really be workable, since all of the things you mention as not being callable 
are actually callable, in the same way `function f() { throw new TypeError(); 
}` is callable.)

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


RE: Determine if a value is Callable/Constructible

2015-03-30 Thread Domenic Denicola
I don’t think [Symbol.call] is a very good mechanism. A new syntactic form 
would make more sense.

It doesn’t seem right that you should have to introduce an observable prototype 
property just to get [[Call]] behavior. (Or a constructor property, if you 
change the syntax to `static [Symbol.call]() { … }`.)

And it raises the question of what happens when I add a [Symbol.call] property 
to other objects. What does it even mean? If I do `var obj = { prototype: { 
[Symbol.call]() { console.log("foo"); } } }`, can I now call `obj()`? Is 
`typeof obj === "function"`? Very strange stuff. Presumably not very 
VM-friendly either, but that's just a guess.

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


Re: Determine if a value is Callable/Constructible

2015-03-30 Thread Yehuda Katz
On Mon, Mar 30, 2015 at 5:36 AM, Caitlin Potter 
wrote:

> >On Mar 30, 2015, at 1:49 AM, Allen Wirfs-Brock 
> wrote:
>
> >There is no intrinsic reason why we needed to mandate that class
> constructors should throw when called.  We even provided a simple and
> straight forward way
> >(new.target===undefined) that a ES constructor body can use to determine
> whether it was called or new’ed.
>
> I don’t think it’s great to have branches in a constructor dealing with
> this — it’s not super-obvious reading the code what it means (so it’s
> another thing to train people to understand).
>

That's exactly my position. The co-mingling of [[Construct]] and [[Call]]
in a single function was a side-effect of having all-singing, all-dancing
functions. The nice thing about ES6 is that we got dedicated syntax for
classes and callbacks. Just because we *can* make constructor functions
serve double-duty via a reflective mechanism doesn't mean that's the right
thing to do.


> A better way (which I think has been suggested by someone already in a
> different thread), would be to have a separate “magic” method to provide
> `call` code.
>
> ```js
> class Buffer {
>   constructor(…a) {
> // …
>   }
>
>   factory(…a) { // [@@factory](), __factory__(), whatever
> return new Buffer(…a);
> // Or whatever else one might wish to do in a factory method
>   }
> }
> ```
>

That was the proposal I made that Allen alluded to:

```js
class Buffer {
  constructor(…a) {
// …
  }

  [Symbol.call](a) {
if (typeof a === 'string') {
  return Buffer.fromString(a);
}

return new Buffer(…arguments);
  }
}
```


>
> But, I think the factory problem is solved well enough with static methods
>
> ```js
> class Buffer {
>   constructor(…a) {
> this.initialize(…a);
>   }
>
>   // Much easier to understand these, compared with Buffer(someBuffer) or
> Buffer(someArray) etc
>   static withBuffer(buffer) { assert(Buffer.isBuffer(buffer)); return new
> Buffer(buffer); }
>   static withArray(array) { assert(Array.isArray(array)); return new
> Buffer(array); }
>   static withSize(size) { assert(IsUInt(size)); return new Buffer(size); }
>   static fromString(str, encoding = “utf8") { assert(IsString(str) &&
> IsString(encoding)); return new Buffer(str, encoding); }
>
>   initialize(…a) {
> switch (a.length) {
>   case 1:
> if (IsUInt(a[0])) return allocateBufferOfSize(this, a[0]);
> else if (Array.isArray(a[0]) return allocateBufferFromArray(this,
> a[0]);
> else if (Buffer.isBuffer(a[0]) return allocateCopyOfBuffer(this,
> a[0]);
> else if (IsString(a[0]) { /* fall through */ }
> else ThrowTypeError(“Function called with incorrect arguments!");
>   case 2:
> if (IsUndefined(a[1]) a[1] = “utf8”;
> if (IsString(a[0] && IsString(a[1]))  return
> allocateBufferFromString(this, a[0], a[1]);
>   default:
> ThrowTypeError(“Function called with incorrect arguments!");
> }
>   }
> }
> ```
>

I agree that static methods are sufficient, but I also agree that it would
be nice to be able to describe existing built-in APIs in terms of classes.
That doesn't, however, mean that we need to force both use-cases into a
single function called *constructor*.

I feel strongly that this:

```js
class Buffer {
  constructor(from) {
// switch on Number, isArray, or Buffer
  }

  [Symbol.call](from, encoding='utf8') {
if (typeof from === 'string') {
  return Buffer.fromString(from, encoding);
}

return new Buffer(from);
  }
}
```

is clearer than:

```js
class Buffer {
  constructor(from, encoding='utf8') {
if (!new.target) {
  if (typeof from === 'string') {
return Buffer.fromString(from, encoding);
  }
}

// switch on Number, isArray, or Buffer
  }
}
```

For one thing, it requires the reader to know that `new.target` is being
used to determine whether the constructor was called with `new`. While it
certainly is expressive enough, it's an unusual reflective operation that
doesn't exactly say what you mean. For another, putting two uses into a
single method and separating them by an `if` is quite often a hint that you
want to break things up into two methods. I think that's the case here.

One of the nice things about the `[Symbol.call]` method is that a reader of
the class can determine at a glance whether it handles [[Call]], and not
have to scan the constructor to see if (and how!) `new.target` is used. And
since `new.target` can also be used for other usages, a reader unfamiliar
with the pattern might not even have a good query to Google (searching
"what is new.target for in JavaScript", even if that works at all, might
likely bring up a bunch of articles about implementing base classes).

>I think we should just drop that throws when called feature of class
> constructors..
> >
> >(The restriction was added to future proof for the possibility of
> inventing some other way to provide a class with distinct new/call

Re: Determine if a value is Callable/Constructible

2015-03-30 Thread Tom Schuster
Thanks Caitlin for actually putting this onto github! I wasn't aware of
that process when I posted about this to the mailinglist. Asking again from
last time: Should we have Type == Object check like Reflect.isExtensible?

-Tom

On Sun, Mar 29, 2015 at 11:51 PM, Caitlin Potter 
wrote:

> **disclaimer** I know this has been brought up before, but bump :>
>
> People are experimenting with polyfilled class implementations, which
> don’t all correctly throw when called as a function (no `new`). Eventually,
> they’re likely to be disappointed that this isn’t legal, and might have to
> undergo some serious pains to fix their applications.
>
> I notice that this is particularly problematic for AngularJS, because
> classes are registered with an injector, which doesn’t know if it can
> `[[Call]]` them or not. It will later on try to `[[Call]]` (depending on
> how the class was registered with DI). It would be really great if we had a
> way to determine if this was going to throw or not, other than looking at
> the
> stringified value of a function, so that these libraries could be updated
> to accomodate new class behaviour without pains (try/catch or processing
> Function.toString())
>
> Some ideas:
>
> Reflect.isConstructor(fn) -> true if Class constructor, generator, or
> legacy (and non-builtin) function syntactic form
> Reflect.isCallable(fn) -> true for pretty much any function, except for
> class constructors and a few builtins
>
> I know it’s way too late for ES6, but maybe some kind of fast-tracked
> extension is in order? it should be pretty simple to implement these (and
> SM and v8 have variations of these in the runtime anyways)
>
> ___
> 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: Determine if a value is Callable/Constructible

2015-03-30 Thread Axel Rauschmayer
> > Don’t the different assumptions as to where the instance is allocated ever 
> > clash here? What if `MySuperClass` were:
> >
> > ```js
> > class MySuperClass extends Error {
> > }
> > ```
> 

> MySubClass preallocates when invoked via new. Just like ES5. So, 
> ```MySuperClass.call(this)``` is same as ES5.  What happens in MySuperClass 
> depends upon the ES6 level programmer.
> 

Right, but I don’t see how an ES5-style constructor MySubContructor can 
allocate its instance and then have it initialized by an ES6 class (where the 
instance is allocated by a super-class). This is about ES5 code being 
confronted with ES6 code and assuming to see a constructor.

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



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


Re: Determine if a value is Callable/Constructible

2015-03-30 Thread Caitlin Potter
>On Mar 30, 2015, at 1:49 AM, Allen Wirfs-Brock  wrote:

>There is no intrinsic reason why we needed to mandate that class constructors 
>should throw when called.  We even provided a simple and straight forward way
>(new.target===undefined) that a ES constructor body can use to determine 
>whether it was called or new’ed.  

I don’t think it’s great to have branches in a constructor dealing with this — 
it’s not super-obvious reading the code what it means (so it’s another thing to 
train people to understand).

A better way (which I think has been suggested by someone already in a 
different thread), would be to have a separate “magic” method to provide `call` 
code.

```js
class Buffer {
  constructor(…a) {
// …
  }

  factory(…a) { // [@@factory](), __factory__(), whatever
return new Buffer(…a);
// Or whatever else one might wish to do in a factory method
  }
}
```

But, I think the factory problem is solved well enough with static methods

```js
class Buffer {
  constructor(…a) {
this.initialize(…a);
  }

  // Much easier to understand these, compared with Buffer(someBuffer) or 
Buffer(someArray) etc
  static withBuffer(buffer) { assert(Buffer.isBuffer(buffer)); return new 
Buffer(buffer); }
  static withArray(array) { assert(Array.isArray(array)); return new  
Buffer(array); }
  static withSize(size) { assert(IsUInt(size)); return new Buffer(size); }
  static fromString(str, encoding = “utf8") { assert(IsString(str) && 
IsString(encoding)); return new Buffer(str, encoding); }

  initialize(…a) {
switch (a.length) {
  case 1:
if (IsUInt(a[0])) return allocateBufferOfSize(this, a[0]);
else if (Array.isArray(a[0]) return allocateBufferFromArray(this, a[0]);
else if (Buffer.isBuffer(a[0]) return allocateCopyOfBuffer(this, a[0]);
else if (IsString(a[0]) { /* fall through */ }
else ThrowTypeError(“Function called with incorrect arguments!");
  case 2:
if (IsUndefined(a[1]) a[1] = “utf8”;
if (IsString(a[0] && IsString(a[1]))  return 
allocateBufferFromString(this, a[0], a[1]);
  default:
ThrowTypeError(“Function called with incorrect arguments!");
}
  }
}
```

>I think we should just drop that throws when called feature of class 
>constructors..
>
>(The restriction was added to future proof for the possibility of inventing 
>some other way to provide a class with distinct new/call behavior. I don’t 
>think we need nor can afford to
>wait for the invention of a new mechanism which will inevitably be more 
>complex than new.target, which we already have.)

I’m all for it if it can be allowed without making classes more complicated for 
consumers to use — The thing I like about requiring `new` is that it’s very 
simple and straight forward.

But in either case, these (IsCallable / IsConstructor) are pretty basic 
qualities of objects that a Reflection* api ought to be able to read into, imho.

> 
> 
>> On Mar 29, 2015, at 11:51 PM, Caitlin Potter  wrote:
>> 
>> ...
>> 
>> Reflect.isConstructor(fn) -> true if Class constructor, generator, or legacy 
>> (and non-builtin) function syntactic form
>> Reflect.isCallable(fn) -> true for pretty much any function, except for 
>> class constructors and a few builtins
> 
> I’ve already seen another situation (node’s Buffer) where code could be 
> simplified by using a ES6 class definition but where that is prevented 
> because a class constructor throws when called.
> 
> Just to clarify something.  Class constructors actually are “callable”.  You 
> can observe this by the fact that Proxy allows you to install an “apply” 
> handler (the reification of the [[[Call]] internal method) on a class 
> constructor.   The the fact that an object can be [[Call]]’ed is already 
> reflected  by the typeof operator.  Class constructors throw when called 
> because at the last minute we choose to make their [[Call]] do an explicit 
> throw not because they aren’t callable.
> 
> There is no intrinsic reason why we needed to mandate that class constructors 
> should throw when called.  We even provided a simple and straight forward way 
> (new.target===undefined) that a ES constructor body can use to determine 
> whether it was called or new’ed.  
> 
> I think we should just drop that throws when called feature of class 
> constructors..
> 
> (The restriction was added to future proof for the possibility of inventing 
> some other way to provide a class with distinct new/call behavior. I don’t 
> think we need nor can afford to wait for the invention of a new mechanism 
> which will inevitably be more complex than new.target, which we already have.)
> 
> Allen
> 
> 

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


Re: Re: Determine if a value is Callable/Constructible

2015-03-30 Thread Peter Flannery
>> On Mar 30, 2015, at 10:12 AM, Axel Rauschmayer 
wrote:
>>
 It doesn’t seem that big of a deal, but one risk is: people mistaking
a class for a constructor, trying to subclass it as if it were a
constructor and things failing silently.

>>> Can you give an example of what you mean?
>>
>> ```js
>> class MySuperClass {}
>>
>> // This function assumes that MySuperClass is an ES5 constructor function
>> function MySubConstructor(foo) {
>>MySuperClass.call(this);
>>this.foo = foo;
>> }
>> MySubConstructor.prototype = Object.create(MySuperClass.prototype);
>> MySubConstructor.prototype.constructor = MySubConstructor;
>> ```
>
> so if MySuperCall didn’t have the throw on [[Call]] behavior the above
would work just fine.
>
> Allen

Would this be a work around? i'm seeing this work with v8 harmony classes
enabled, or is this something that wont work eventually?
```js
function MySubConstructor(foo) {
  MySuperClass.constructor.call(this)
  this.foo = foo;
}
```

I also noticed that using apply to chain constructors won't work either as
currently mentioned at Mozilla [Using apply to chain constructors](
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply#Example:_Using_apply_to_chain_constructors
)

```js
//
function applyConstructor(ctor, args) {
var child = Object.create(ctor.prototype);
var result = ctor.apply(child, args); // !!! throws Class constructors
cannot be invoked without 'new'
return result && Object(result) === result ? result : child;
}
```

but this still seems to work
```js
function applyConstructor(ctor, args) {
return new (Function.prototype.bind.apply(ctor, [null].concat(args)));

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


Re: Determine if a value is Callable/Constructible

2015-03-30 Thread Claude Pache

> Le 30 mars 2015 à 10:46, Allen Wirfs-Brock  a écrit :
> 
>> 
>> On Mar 30, 2015, at 10:12 AM, Axel Rauschmayer  wrote:
>> 
 It doesn’t seem that big of a deal, but one risk is: people mistaking a 
 class for a constructor, trying to subclass it as if it were a constructor 
 and things failing silently.
 
>>> Can you give an example of what you mean?
>> 
>> ```js
>> class MySuperClass {}
>> 
>> // This function assumes that MySuperClass is an ES5 constructor function
>> function MySubConstructor(foo) {
>>MySuperClass.call(this);
>>this.foo = foo;
>> }
>> MySubConstructor.prototype = Object.create(MySuperClass.prototype);
>> MySubConstructor.prototype.constructor = MySubConstructor;
>> ```
> 
> so if MySuperCall didn’t have the throw on [[Call]] behavior the above would 
> work just fine.
> 
> Allen

I see an issue when MySuperClass contains itself a super() invocation... at 
least when that super-class is some builtin that doesn't support initialisation 
of pre-allocated instances, like `Array`. As currently specified, it will just 
throw, which is at least safe. It would be interesting to make it just work 
without hacks such as `if (new.target) super(); else super.constructor(...);`, 
and, in the same time, without silently break with `Array`, etc.

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


Re: Determine if a value is Callable/Constructible

2015-03-30 Thread Axel Rauschmayer
> On Mar 30, 2015 10:54 AM, Axel Rauschmayer  wrote:
> >>>
> >>> ```js
> >>> class MySuperClass {}
> >>>
> >>> // This function assumes that MySuperClass is an ES5 constructor function
> >>> function MySubConstructor(foo) {
> >>>MySuperClass.call(this);
> >>>this.foo = foo;
> >>> }
> >>> MySubConstructor.prototype = Object.create(MySuperClass.prototype);
> >>> MySubConstructor.prototype.constructor = MySubConstructor;
> >>> ```
> >>
> >>
> >> so if MySuperCall didn’t have the throw on [[Call]] behavior the above 
> >> would work just fine.
> >
> >
> > In general, I’d expect this kind of subclassing to fail, due to the new 
> > instantiation protocol. Wrong?
> 
> Would work fine if throw semantics removed and invoked as
> ```js
> new MySubConstructor();
> ```
> Just like ES5.
> 
> If invoked as
> ```js
> MySubConstructor();
> ```
> would fail just like ES5.
> 
> Throwing on [[Call]] is a compatibility hazard.
> 


Don’t the different assumptions as to where the instance is allocated ever 
clash here? What if `MySuperClass` were:

```js
class MySuperClass extends Error {
}
```

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



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


Re: Determine if a value is Callable/Constructible

2015-03-30 Thread Axel Rauschmayer
>> ```js
>> class MySuperClass {}
>> 
>> // This function assumes that MySuperClass is an ES5 constructor function
>> function MySubConstructor(foo) {
>>MySuperClass.call(this);
>>this.foo = foo;
>> }
>> MySubConstructor.prototype = Object.create(MySuperClass.prototype);
>> MySubConstructor.prototype.constructor = MySubConstructor;
>> ```
> 
> so if MySuperCall didn’t have the throw on [[Call]] behavior the above would 
> work just fine.

In general, I’d expect this kind of subclassing to fail, due to the new 
instantiation protocol. Wrong?

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



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


Re: Determine if a value is Callable/Constructible

2015-03-30 Thread Allen Wirfs-Brock

> On Mar 30, 2015, at 10:12 AM, Axel Rauschmayer  wrote:
> 
>>> It doesn’t seem that big of a deal, but one risk is: people mistaking a 
>>> class for a constructor, trying to subclass it as if it were a constructor 
>>> and things failing silently.
>>> 
>> Can you give an example of what you mean?
> 
> ```js
> class MySuperClass {}
> 
> // This function assumes that MySuperClass is an ES5 constructor function
> function MySubConstructor(foo) {
> MySuperClass.call(this);
> this.foo = foo;
> }
> MySubConstructor.prototype = Object.create(MySuperClass.prototype);
> MySubConstructor.prototype.constructor = MySubConstructor;
> ```

so if MySuperCall didn’t have the throw on [[Call]] behavior the above would 
work just fine.

Allen

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


Re: Determine if a value is Callable/Constructible

2015-03-30 Thread Axel Rauschmayer
>> It doesn’t seem that big of a deal, but one risk is: people mistaking a 
>> class for a constructor, trying to subclass it as if it were a constructor 
>> and things failing silently.
>> 
> Can you give an example of what you mean?

```js
class MySuperClass {}

// This function assumes that MySuperClass is an ES5 constructor function
function MySubConstructor(foo) {
MySuperClass.call(this);
this.foo = foo;
}
MySubConstructor.prototype = Object.create(MySuperClass.prototype);
MySubConstructor.prototype.constructor = MySubConstructor;
```

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



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


Re: Determine if a value is Callable/Constructible

2015-03-30 Thread Allen Wirfs-Brock

> On Mar 30, 2015, at 8:40 AM, Axel Rauschmayer  wrote:
> 
> It doesn’t seem that big of a deal, but one risk is: people mistaking a class 
> for a constructor, trying to subclass it as if it were a constructor and 
> things failing silently.
> 
Can you give an example of what you mean?

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


Re: Determine if a value is Callable/Constructible

2015-03-30 Thread Allen Wirfs-Brock

> On Mar 30, 2015, at 8:09 AM, Yehuda Katz  wrote:
> 
> ...
> 
> I don't think this is an accurate representation of the discussion we had.

It’s my characterization of the situation and reflects my position. I agreed to 
disabling calling class constructors via a throw in order to get the consensus 
necessary to move forward with finishing ES6.  However, I also think that that 
restriction was technically unnecessarily and crippling for some use cases.  I 
know you have some, as yet not fully specified, alternative in mind. I don’t 
know its details so I can’t directly comment on it. But,  I’m skeptical that of 
the need for anything other than new.target and I’m pretty sure that any 
alternative will be move complex and take longer to get into implementations.

Allen



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