Brandon Benvie (2013-07-16T23:42:55.000Z)
On 7/16/2013 4:10 PM, Erik Arvidsson wrote:
> All of the new constructors, Map, Set, WeakMap and WeakSet should fail
> when called as a function unless `this` already has a certain internal
> property, ie [[MapData]]. This is so that sub classing works as
> expected.
>
> However, all JS engines that supports Map, Set and WeakMap are future
> hostile and they all return a new instance when called as a function.
> For example, here is the V8 code:
>
> function MapConstructor() {
>    if (%_IsConstructCall()) {
>      %MapInitialize(this);
>    } else {
>      return new $Map();
>    }
> }
>
> I understand that fully supporting @@create requires a lot of work but
> until then we should at least throw when called as function to allow
> us to get out of this mess eventually.
>

I wonder if the current spec language is a remnant of before @@create 
was added to the spec. It should be possible to detect when the 
constructors are called with a receiver that is not an initializing 
instance and simply create a new instance. Pseudo code:

function Map(...args){
   if (!IsObject(this) || !%HasMapData(this)) {
     // got a primitive, the global object, or some random object like 
from `Map.call({})`
     return new Map(...args);
   } else if (!%IsInitializedMap(this)) {
     // A legit Map but has uninitialized [[MapData]]
     %MapInitialize(this);
   } else {
     // [[MapData]] is present but is already initialized
     throw TypeError("Attempted to reinitialize a Map");
   }
}


The main point of introducing @@create (I think) was to allow for 
distinguishing between initializing, initialized, and everything else.
domenic at domenicdenicola.com (2013-07-18T16:31:46.661Z)
I wonder if the current spec language is a remnant of before @@create 
was added to the spec. It should be possible to detect when the 
constructors are called with a receiver that is not an initializing 
instance and simply create a new instance. Pseudo code:

```js
function Map(...args){
   if (!IsObject(this) || !%HasMapData(this)) {
     // got a primitive, the global object, or some random object like from `Map.call({})`
     return new Map(...args);
   } else if (!%IsInitializedMap(this)) {
     // A legit Map but has uninitialized [[MapData]]
     %MapInitialize(this);
   } else {
     // [[MapData]] is present but is already initialized
     throw TypeError("Attempted to reinitialize a Map");
   }
}
```

The main point of introducing @@create (I think) was to allow for 
distinguishing between initializing, initialized, and everything else.