Array length property wrap-around

Kent Hansen khansen at
Wed Nov 19 08:41:20 PST 2008

What's supposed to happen when one of the built-in methods (e.g. 
Array.prototype.push) tries to assign a value greater than 4294967295 to 
the length property?

js> a = new Array(4294967295); a.push("foo")

i.e. the length becomes 0. This also happens if you apply push to 
non-Array instances, which don't have the length property constraint 
described in 15.4.
Step 5 of says to "increase n by 1", but it does not say that n 
should wrap around to 0 if  the new value can't be represented as a 
32-bit unsigned integer (the ToUint32 conversion is only done when 
assigning the initial value of n, in step 2).
If I interpret the spec correctly, n should become 4294967296, and step 
7 should then cause a RangeError when trying to assign the new length.
In the implementations I've tried, this is not the case, and instead you 
get this interesting behavior:

js > a = new Array(4294967294); a.push("foo", "bar")
js> a[4294967294]

Oops; the length invariant broke. With WebKit:

jsc > a = new Array(4294967294); a.push("foo", "bar")
jsc> a[4294967294]

Oops; all the properties 0,1,2,...,4294967294 were wiped out.

I also question step 2 of Why is the narrow ToUint32 
conversion necessary; shouldn't it be a variant of ToInteger? We know 
that for Array instances, the invariant on the length property holds 
anyway, so the result of the conversion will be the same; but using 
ToUint32 makes the function less generic:

js> o = { length: 4294967296 };, "foo")

Pretending I hadn't read the spec, I would have expected the above to 
create a property named "4294967296" and increase length by 1; no 32-bit 
conversion imposed.
Looking at the other functions in Array.prototype I see that they do 
ToUint32 on the length too, so this change might become a bit large and 
dangerous. Still, the undefined behavior /  data loss irks me.

Best regards,

More information about the Es-discuss mailing list