Edit: Simpler repro case; the following code:
setInterval(function(){
var a=[10,20,30,40], i=-1;
a[-1] = 42;
while (i<10000) a[i++];
console.log(a[-1],a[4294967295]);
},100);
…produces the output:
42 undefined
undefined 42
42 undefined
37x undefined 42
42 undefined
undefined 42
42 undefined
41x undefined 42
42 undefined
undefined 42
42 undefined
(Original question follows)
Given the following code (or code like it (fiddle)):
<!DOCTYPE HTML>
<html><head><title>-1 Array Index</title></head><body>
<label>p: <input id="p" size="3"></label>
<script type="text/javascript">
var p = document.getElementById('p');
p.onkeyup = function(){
var a = "10 20 30 40".split(/\s+/);
foo(a, p.value*1);
}
function foo(a,p){
var count=a.length, i=0, x;
if (p) a[i=-1]=p;
while (i<10000) x = a[i++ % count];
console.dir(a);
}
</script>
</body></html>
I see the following in the Developer Console when I focus the "p" input and type 1 backspace 2:
Once I see the index of 4294967295
(232 - 1) show up, things sometimes begin to "go bad": sometimes the Developer Tools automatically close, sometimes all Safari tabs freeze and require a relaunch to recover.
Oddly, I can't repro this if I remove the (largely useless in this case) while loop. And I can't repro this on Chrome or Firefox.
Can anyone shed any light on what could possibly be at the root of this problem?
This is occurring with Safari 5.1.7 on OS X 10.7.4
Using negative indices may result in undefined behaviour.
According to the ECMAScript documentation, a particular value p
can only be an array index if and only if:
(p >>> 0 === p) && (p >>> 0 !== Math.pow(2, 32) - 1)
In your case:
# -1 >>> 0
4294967295
# Math.pow(2, 32) - 1
4294967295
edit
If p
fails above test, it should be treated as a regular object property like a.foo
or a['foo']
. That said, as it turns out, setting the negative index with a string cast works around the issue.
a['' + (i =-1)] = p
Conclusion: browser bug
This sounds like a bug in JavaScriptCore to me. Perhaps foo
is being JITted when it's called the second time and the JITted code introduces the bug.
I'd recommend filing a bug against JavaScriptCore and attaching your test case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With