On Nov 16, 2014, at 11:08 PM, Tom Van Cutsem wrote:

> 2014-11-17 3:34 GMT+01:00 Frankie Bagnardi <f.bagna...@gmail.com>:
> Consider when Array.isArray would be used.  In my experience, checks to see 
> if something is an array are used for:
> 
>  - deciding how to iterate it (for(;;) vs for..in, for example)
> 
> This is a good one. Here, again, a typical proxy-for-array would work as 
> intended, as the for(;;) loop just queries .length and properties named "0", 
> "1", ... via standard [[Get]] access.
> 
> Can someone come up with a convincing example where a proxy-for-array would 
> *not* work as intended?
> ("convincing" here means it doesn't involve a proxy that blatantly violates 
> the Array contract on purpose)

Probably not, because the Array.prototype methods are all carefully coded to 
not have any internal slot or this identify dependencies.

But probing through the proxy as has been proposed is a terrible violation of 
the MOP API boundary and isn't generalizable to other built-ins that are 
dependent upon internal state. While a null handler proxy on a direct instance 
of Array would work under that design, a comparable Map.isMap or 
Promise.isPromise method would not.  Rather than a one-off hack I think we 
should use a new pattern that is generalizable:


Here is a proposal:

Array.isArray is redefined equivalently to:

```js
Array.isArray = function (obj) {
   let constructor = obj.constructor;
   If (typeof constructor != 'function') return false;
   return !!constructor[Symbol.isArray];
}
```

and also

```js
Array[Symbol.isArray]] = true;  //note, this is a constructor property, not an 
Array.prototype property.
```

we also change Array.prototype.concat to do the above Array.isArray test 
instead of using @@comcatSpreadable and change JSON.stringify to use this test 
where it current checks for an exotic array object.

Then we have the following:

assert(Array.isArray( [ ] ));  //just like ES5
assert( ! Array.isArray( Object.create(Array.prototype))); //just like ES5
assert (new class extends Array{});  //ES6 Array subclass instances answer true 
unless the subclass over-rides the static  @@isArray property
assert(new class extends Array {
   constructor() {return {}};
});   // even if the subclass instance isn't an exotic array object (this is an 
improvement over the current ES6 spec. which says that 
       //isArray answers false in this case
assert(new Proxy( [ ], { });  //because it's all done with property access, no 
instance inspection required.

assert( ! new Int32Array(10));  //not array-like, just like ES5

However, I think we should experiment with giving %TypedArrau% is true valued 
@@isArray property.  I'm guessing that this change won't actually break 
anything.

the above proposal completely decouples Array.isArray from exotic array object 
checking or any other direct instance inspection. Everything works at the 
property access level and so is (by default) transparent to proxies and 
completely controllable at the ES cod level. 

allen

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

Reply via email to