Bug 95309
| Summary: | Sorting array with objects using a custom function returns strange result if array length > 10 | ||
|---|---|---|---|
| Product: | WebKit | Reporter: | Hristo Chakarov <mail> |
| Component: | JavaScriptCore | Assignee: | Nobody <webkit-unassigned> |
| Status: | RESOLVED INVALID | ||
| Severity: | Major | CC: | ap, barraclough, oliver |
| Priority: | P3 | ||
| Version: | 528+ (Nightly build) | ||
| Hardware: | Mac (Intel) | ||
| OS: | OS X 10.7 | ||
Hristo Chakarov
I have array with objects, which have a key on which I want to sort. It's obvious I have to use custom sorting fn.
When the array length is <= 10 everything works as it should. But if the array has > 10 elements in it sorting screws up.
Here are two examples:
1. Open JavaScript console in Google Chrome/Apple Safari browser and copy paste the following code & execute:
JSON.stringify( [{p:'03'},{p:'06'},{p:'10'},{p:'01'},{p:'04'},{p:'02'},{p:'05'},{p:'08'},{p:'07'},{p:'09'}].sort( function ( a, b ) {
return b.p < a.p;
}) );
Returned result is correct:
"[{"p":"01"},{"p":"02"},{"p":"03"},{"p":"04"},{"p":"05"},{"p":"06"},{"p":"07"},{"p":"08"},{"p":"09"},{"p":"10"}]"
2. Now lets add 1 more element to the array:
JSON.stringify( [{p:'03'},{p:'06'},{p:'10'},{p:'01'},{p:'04'},{p:'02'},{p:'05'},{p:'08'},{p:'07'},{p:'09'},{p:'11'}].sort( function ( a, b ) {
return b.p < a.p;
}) );
Returned result is wrong:
"[{"p":"02"},{"p":"03"},{"p":"01"},{"p":"04"},{"p":"05"},{"p":"06"},{"p":"07"},{"p":"08"},{"p":"09"},{"p":"10"},{"p":"11"}]"
Issue not observed in all non-webkit browsers (Firefox, IE).
| Attachments | ||
|---|---|---|
| Add attachment proposed patch, testcase, etc. |
Alexey Proskuryakov
> return b.p < a.p;
This is not a correct comparison function - it should return -1, 1, or 0 when elements are equal.
I don't know if we want to track a difference with Firefox like this one as a bug. The spec explicitly states that behavior with inconsistent comparison functions is implementation defined.
Oliver Hunt
Your comparison function is bogus.
You return (in essence) a < b.
Which is a bool, so converts to 0 or 1 (false, true)
Per spec, a result of 0 means that the two values are the same, so if we end do compare(3,1) we will get a result of 0 (3 and 1 are the same value for the purposes of sorting) but if we do compare(1,3) we will get a result of 1 (1 is greater than 3, for the purpose of sorting).
Hence the results are inconsistent and we can't guarantee anything sensible will come out the other end.