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

Allen Wirfs-Brock allen at wirfs-brock.com
Mon Nov 17 17:04:50 PST 2014


On Nov 17, 2014, at 2:30 PM, Allen Wirfs-Brock wrote:

> 
> On Nov 17, 2014, at 11:06 AM, Brendan Eich wrote:
> 
>> Allen Wirfs-Brock wrote:
>>> ```js
>>> Array[Symbol.isArray]] = true;  //note, this is a constructor property, not an Array.prototype property.
>> 
>> Minomer, then -- how about Symbol.isArrayClass?
> 
> perhaps, I have a negative reaction to including the work "class" but can probably live with it.
> 
>> 
>>> 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
>> 
>> How so? True:
>> 
>> js> Array.isArray(Array.prototype)
>> true
>> js> Array.isArray(Object.create(Array.prototype))
>> false
>> 
>> but constructor isn't shadowed:
>> 
>> js> Array.prototype.constructor
>> function Array() {
>>   [native code]
>> }
>> js> Object.create(Array.prototype).constructor
>> function Array() {
>>   [native code]
>> }
> 
> Shit, you're right.  This is the hard case for legacy compat using this technique. 
> 
> I think I see a way to make this give the legacy answer, but I suspect I can't make it give the same answer for
>  Array.isArray(new Proxy(Object.create(Array.prototype), { }));
> May limiting the WTF=ness to that case isn't so bad.

OK, this should deal with the Object.create(Array.prototype) case

Array.isArray = function isArray(obj) {
   let constructor = obj.constructor;
   If (typeof constructor != 'function') return false;
   let construictorIs be Object.getOwnPropertyDescript(constructor,"isArray");
   if (constructorIs) {
       //the constructor has an isArray property, so we'll assume it is a built-in Array constructor
       if (isOrdinaryObject(obj)) return false;  //The Object.create(Array.prototype) legacy compat. case.
       if (isProxy(obj)) return isArray(getProxyTarget(obj)); //Array.isArray(new Proxy(Object.create(Array.prototype), {}))
       //I'm not sure that the above line is really a compat. issue. I'd prefer to leave it out.
   }
   return !!constructor[Symbol.isArray];
}


It takes a little hackery to deal with the legacy Object.create(Array.prototype) cases but for ES6 subclasses and non-subclasses such as typed arrays it doesn't perform any exotic instance sniffing.

Allen




More information about the es-discuss mailing list