Allen Wirfs-Brock (2014-06-11T16:44:04.000Z)
On Jun 11, 2014, at 7:24 AM, Domenic Denicola wrote:

> A variety of places in the spec use the new IsConstructor abstract operation. In ES5, this test (essentially, "does the object implement the [[Construct]] internal method") was restricted to the `new` operator. But in ES6, it is used in implementing a large variety of built-in functions:
> 
> - All Array methods
> - All %TypedArray% methods
> - All Promise methods (via NewPromiseCapability)
> 
> (Note that there are two uses: arrays and typed arrays do alternative logic for non-constructors; promises fail immediately. This inconsistency might be a bug?)

Maybe you're looking at things differently from me, but I only see use of IsConstructor in a few Array methods, not all of them.

For most places in the spec. if you trace the logic of the algorithms that use IsConstructor it be being used as a guard on a [[Construct]] call and the alternative path is to throw a TypeError.  In ES code this would be done automatically by the 'new' operator but must be done explicitly in the pseudo-code. A  JS self-hosted implementation of those algorithm that used 'new' would not need to do an explicit IsConstructor test in most of those cases.

There are a few uses of IsConstructor in some Array methods that deal with subtle backwards compat issues that are a result of extending Array to be subclassable.  These are very unique cases and I don't think you should look at them as establishing a pattern that should be followed in other situations.

Array.from and Array.of have a non-throwing IsConstrutor test because they are designed to allow things like this:

let of = Array.of;
of(1,2,3,4,5);   //Equivalent to: Array.of(1,2,3,4,5)

I don't recall why we provided that functionality.  It doesn't seem to me like a pattern we should want to encourage.

> 
> It seems to me that we should expose this primitive reflective operation to users, instead of having all of these methods be able to detect something that user code can't, and thus making them harder to explain or polyfill.

Most of these uses are simply emulating the behavior of the 'new' operator so it really shouldn't be needed to be tested explicitly in a polyfill.  When it is really need, a user land IsConstructor test can be written using Proxy.
> 
> 
> Alternately, if we don't think users should be doing this kind of reflection, then we probably shouldn't be doing it ourselves. In which case, figuring out an alternate path for the above methods would be useful---perhaps they simply try to construct, and fail immediately if used with a non-constructible object, instead of falling back.
> 
> WDYT?

Other than the Array.of and Array.from usages the other uses are all necessary either functionally (you can't just "try to construct" by calling [[Construct]], it requires an explicit guard) or to deal with special backwards compat situations.

I'd be happy to eliminate the special handling in Array.of and Array.from if there is consensus that it isn't desirable.

Allen
domenic at domenicdenicola.com (2014-06-20T19:25:32.754Z)
On Jun 11, 2014, at 7:24 AM, Domenic Denicola wrote:

> A variety of places in the spec use the new IsConstructor abstract operation. In ES5, this test (essentially, "does the object implement the [[Construct]] internal method") was restricted to the `new` operator. But in ES6, it is used in implementing a large variety of built-in functions:
> 
> - All Array methods
> - All %TypedArray% methods
> - All Promise methods (via NewPromiseCapability)
> 
> (Note that there are two uses: arrays and typed arrays do alternative logic for non-constructors; promises fail immediately. This inconsistency might be a bug?)

Maybe you're looking at things differently from me, but I only see use of IsConstructor in a few Array methods, not all of them.

For most places in the spec. if you trace the logic of the algorithms that use IsConstructor it be being used as a guard on a [[Construct]] call and the alternative path is to throw a TypeError.  In ES code this would be done automatically by the 'new' operator but must be done explicitly in the pseudo-code. A  JS self-hosted implementation of those algorithm that used 'new' would not need to do an explicit IsConstructor test in most of those cases.

There are a few uses of IsConstructor in some Array methods that deal with subtle backwards compat issues that are a result of extending Array to be subclassable.  These are very unique cases and I don't think you should look at them as establishing a pattern that should be followed in other situations.

`Array.from` and `Array.of` have a non-throwing IsConstructor test because they are designed to allow things like this:

```js
let of = Array.of;
of(1,2,3,4,5);   //Equivalent to: Array.of(1,2,3,4,5)
```

I don't recall why we provided that functionality.  It doesn't seem to me like a pattern we should want to encourage.

> 
> It seems to me that we should expose this primitive reflective operation to users, instead of having all of these methods be able to detect something that user code can't, and thus making them harder to explain or polyfill.

Most of these uses are simply emulating the behavior of the 'new' operator so it really shouldn't be needed to be tested explicitly in a polyfill.  When it is really need, a user land IsConstructor test can be written using Proxy.
> 
> 
> Alternately, if we don't think users should be doing this kind of reflection, then we probably shouldn't be doing it ourselves. In which case, figuring out an alternate path for the above methods would be useful---perhaps they simply try to construct, and fail immediately if used with a non-constructible object, instead of falling back.
> 
> WDYT?

Other than the Array.of and Array.from usages the other uses are all necessary either functionally (you can't just "try to construct" by calling [[Construct]], it requires an explicit guard) or to deal with special backwards compat situations.

I'd be happy to eliminate the special handling in Array.of and Array.from if there is consensus that it isn't desirable.