for/for-each iteration order is more inconsistent than documented for Array and XML

RESOLVED WONTFIX

Status

P3
enhancement
RESOLVED WONTFIX
10 years ago
5 months ago

People

(Reporter: ben.garney, Unassigned)

Tracking

unspecified
Q1 12 - Brannan
Dependency tree / graph
Bug Flags:
flashplayer-qrb +

Details

(Reporter)

Description

10 years ago
User-Agent:       Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.19 (KHTML, like Gecko) Chrome/1.0.154.42 Safari/525.19
Build Identifier: Flash Player 10,0,12,36

Dense arrays and XML nodes iterate in order when using for/for each, while other iteration scenarios (object properties, Dictionary, non-dense arrays) exhibit an order dependent on memory allocation patterns.

The VM does not need to enforce an order in every situation. However, I experienced some very frustrating issues where running under the debug player gave different results than running under the release player, because memory allocation patterns changed slightly, and as a result debug would let me iterate in the order I added items to an Array, while release gave me a different order.

For instance, this unit test passes on debug player and fails on release player:

        public function testArrayOrder():void
        {
           var a:Array = new Array();
           a["DoReload"] = 1;
           a["ContinueShooting"] = 2;
           a["StopShooting"] = 3;
           
           var expectedValue:int = 1;
           for each(var n:int in a)
           {
              assertEquals(n, expectedValue);
              expectedValue++;
           }
        } 

This was a painful discovery and cost a few days of dev time. In addition, because iteration order is dependent on memory allocation patterns, it had the appearance of a compiler or VM bug - adding or removing trace() calls elsewhere in the program altered the memory allocation pattern and made the issue intermittently go away.

Based on my experiences, I'd like to suggest three possible solutions, in order from least work to most:

1. Update the Flex docs to indicate which scenarios ARE ordered, and which are not. 
2. In debug player, randomize the iteration order per-run so that code which relies on an iteration order breaks early.
3. Provide a built-in Array-like container which preserves iteration order based on the order fields were added. PHP's associative arrays work like this and it's often useful. (Obviously AS3 and PHP are different languages and it may not make sense to have this, but it's good to look at a feature and know that it's been tried.)

http://coderhump.com/archives/322 has a little more context/information. It is a post on my personal blog about my experience with this issue.

Reproducible: Sometimes

Steps to Reproduce:
See details; run unit test. Unit test behavior is dependent on memory allocation order. Changing the other code in the test app may change the results of the test.
Actual Results:  
Test passes on debug player, fails on release player.

Expected Results:  
Should be same for both players. If order is not guaranteed, should fail on both (at least some of the time).
(Reporter)

Comment 1

10 years ago
For the debugger randomization, maybe the app could generate a random seed at startup and XOR it into its hash keys? (Right around http://hg.mozilla.org/tamarin-central/file/2cee46be9ce0/core/avmplusHashtable.cpp#l125) 

That would give consistent within-run but changing order, which would make code with assumptions about iteration order fail-early.

Comment 2

10 years ago
Flex docs: "Object properties are not kept in any particular order, so properties may appear in a seemingly random order. "
Severity: normal → enhancement
OS: Windows XP → All
Hardware: x86 → All
(Reporter)

Comment 3

10 years ago
That's true. However, in some cases, iteration is in order. (In the case of Array, it is ordered if the Array is dense, otherwise it is random. XML content is iterated in order. Sometimes you may get "lucky" and get a certain order from an object or dictionary, too.)

As far as I can tell, the docs don't discuss these scenarios. The XML and dense Array cases might be worth mentioning. Any other situations with defined iteration orders might be worth mentioning, too, if there are any.

Additionally, in order to keep people from relying on a specific order of iteration that they get by accident, it might be wise to slightly modify the hash table implementation in the debug player so that they are more likely to encounter inconsistent behavior while they are developing and fix the problem, rather than only discovering it when they release their app.

As it is, the behavior appears consistent (it is consistent between runs of the same SWF with the same player binary), then breaks when other environmental factors change, which is hard to debug and implies that e.g. the release player is broken when really it is the user's code that is wrong.

Updated

10 years ago
Flags: flashplayer-qrb+
Priority: -- → P4
Target Milestone: --- → Future

Updated

10 years ago
Status: UNCONFIRMED → NEW
Ever confirmed: true
Priority: P4 → --

Updated

9 years ago
Depends on: 535770

Updated

9 years ago
Blocks: 563598

Updated

9 years ago
Priority: -- → P3
Target Milestone: Future → flash10.2

Updated

8 years ago
Target Milestone: Q3 11 - Serrano → Q1 12 - Brannan
(thought this was array-correctness issue at first, but comment 2 points out that the current behavior may fit our spec.  so leaving out of that tracker for now.  it might be a ecma-compliance issue, though.)
No longer blocks: 700686
Tamarin is a dead project now. Mass WONTFIX.
Status: NEW → RESOLVED
Last Resolved: 5 months ago
Resolution: --- → WONTFIX
Tamarin isn't maintained anymore. WONTFIX remaining bugs.
You need to log in before you can comment on or make changes to this bug.