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