Array.isArray(new Proxy([], {})) should be false (Bug 1096753)

Allen Wirfs-Brock allen at
Mon Nov 17 09:30:32 PST 2014

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

> 2014-11-17 3:34 GMT+01:00 Frankie Bagnardi <f.bagnardi at>:
> 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 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:

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

and also

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. 


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the es-discuss mailing list