UPDATE 2011.09.13 This bug has been resolved by Adobe. The example
code below now exhibits the correct behavior. Original question is below.
It took me many hours to narrow down a problem in some code to this reproducible error, which seems to me like a bug in AVM2. Can anyone shed light on why this is occurring or how to fix it?
When the value at index 1 is deleted and a value is subsequently set at index 0, the non-existent (undefined) value at index 1 will now show up in a foreach loop. I have only been able to produce this outcome with index 1 and 0 (not any other n and n-1).
Run this code:
package
{
import flash.display.Sprite;
public class Main extends Sprite
{
public function Main():void
{
var bar : Array = new Array(6);
out(bar);
//proper behavior
trace("bar[1] = 1", bar[1] = 1);
out(bar);
//proper behavior
trace("delete bar[1]", delete bar[1]);
out(bar);
//proper behavior
trace("bar[4] = 4", bar[4] = 4);
out(bar);
//for each loop will now iterate over the undefined position at index 1
trace("bar[0] = 0", bar[0] = 0);
out(bar);
trace("bar[3] = 3", bar[3] = 3);
out(bar);
}
private function out(bar:Array):void
{
trace(bar);
for each(var i : * in bar)
{
trace(i);
}
}
}
}
It will give this output:
,,,,,
bar[1] = 1 1
,1,,,,
1
delete bar[1] true
,,,,,
bar[4] = 4 4
,,,,4,
4
bar[0] = 0 0
0,,,,4,
0
undefined
4
bar[3] = 3 3
0,,,3,4,
0
undefined
4
3
EDIT: See answer for likely cause of the bug. Unable to find a fix. My solution was to code a special case where if index 0 is being set and index 1 does not exist, delete index 1 after setting index 0. Not exactly an elegant solution :\
It looks like you’re running in to a bug that seems to happen when AS3 arrays are split into a dense array part and a “rest” hashtable part.
It’s been reported as an “Actionscript Core Language” bug to Adobe here: FP-3477
There’s also a couple of blog-post links there to other developers that have run into the (probably) same issue.
Although your example code doesn’t re-insert the same object, there might be related issues to how the VM is optimizing low-range literal numbers (often as shared, constant ‘objects’)