Array.prototype.concat result length (ES5.1)

Allen Wirfs-Brock allen at wirfs-brock.com
Thu Jul 14 12:35:26 PDT 2011


On Jul 14, 2011, at 10:39 AM, Brendan Eich wrote:

> On Jul 14, 2011, at 10:04 AM, Allen Wirfs-Brock wrote:
> 
>> This appears to be a (possible) specification bug that first occurs in ES3 and which was not corrected in ES5.
>> 
>> I appears in concat and push. But no other algorithms.  The problem occurs when when a length value is incremented and then used as an array index without first applying ToUint32 to the value.  It only occurs concat and push because all the other algorithms are bounded by a length value that has had ToUint32 applied to it.
> 
> FYI, SpiderMonkey (Firefox) results:
> 
> js> a=[]
> []
> js> a.length=0xffffffff
> 4294967295
> js> b=a.concat([1])
> []
> js> b.length
> 0
> 
> js> a=[]
> []
> js> a.length=0xffffffff
> 4294967295
> js> a.push(1)
> typein:3: RangeError: invalid array length
> 

The range error comes from the special [[DefineOwnProperty]] internal method of array objects. According to the spec. the above push test should create  a property with key "4294967295"  (not an array indexed property) and then throw (when the length is set).  So, a should sill have the added property if examined after the exception.  If a is not an array instance it should get the property and length should get set to  4294967296.

The reason, that the concat test doesn't throw is probably because of the missing [[Put]] of length that was the original topic of this thread.
...
>> We have to possible courses of action:
>>    1) consider the specification to be correct as written. 
>>    2) consider this to be a spec. but that we correct in the errata and in future editions.
>> 
>> This is an edge case that probably never occurs in the real world so the choice probably has no real impact.  #1 is most consistent with the rest of the ES spec.  However, the 2^32 length wrap semantics of arrays is kind of bogus and it might be nice to try to eliminate it in the future.  #2 would be a step away from that.
>> 
>> this now bug: https://bugs.ecmascript.org/show_bug.cgi?id=131 
> 
> Would appreciate Jeff's thoughts. I've learned my lesson many times on wraparound being wrong, so I'm in favor of RangeError. We do that for push but not concat in SpiderMonkey, so AFAIK we could just fix concat, as you note no one would care except our testsuites, and we'd be safer and more consistent at the margin.

But as noted above, the range error is only specified for actual array instances and not for generic array-like objects.

What about the possibility of simply eliminating the range error and the Uint32 restriction on the association between array indexed properties and the "length" property.  Instead replace it with a ToInteger constraint.  This is essentially how string operations are defined. Implementations could still optimize for lengths <2^32 and or any other size they deemed appropriate.

Allen
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20110714/c74d1043/attachment.html>


More information about the es-discuss mailing list