archives

« Bugzilla Issues Index

#2978 — Array.prototype.sort: specify the expected behaviour of, e.g., `[Infinity, -Infinity].sort( (a, b) => a - b )`


Consider the following code:

let compareFn = (a,b) => a - b
[Infinity, 9, 3, 4 , -Infinity, 6, Infinity, 2].sort(compareFn)

The behaviour of the `sort` method is left undefined by the spec, because the `compareFn` produce `NaN` instead of `0` in the following case:

compareFn(Infinity, Infinity)

However, four browsers I've tried (latest stable versions of Safari, Firefox, IE and Chrome) do produce the expected result in that particular example.

That case could be easily specified by allowing `compareFn(a, b)` to produce any number including `NaN`, and by requiring to treat `NaN` the same way as `0`.


fixed in rev26 editor's draft


in rev26


What if NaNs appear in the list to be sorted?


(In reply to Mark Miller from comment #3)
> What if NaNs appear in the list to be sorted?

Some experience with current browsers show inconsistent results (generally an incompletely sorted array).

js> [NaN, 4, 2, NaN, 1, NaN, 3].sort(function(a, b) { return a - b })

Safari 7: [NaN, 1, 2, 4, NaN, NaN, 3]
Firefox 31: [3, NaN, 1, NaN, 2, 4, NaN]
Chrome 36: [NaN, 2, 4, NaN, 1, NaN, 3]
IE 11: [NaN, 2, 4, NaN, 1, NaN, 3]


This is maybe nitpicking, but...

The change made in Rev. 26 has consisted of adding a special case for NaN in the SortCompare Abstract Operation algorithm (Section 22.1.3.24.1; step 17.d).

Now: In case `comparefn` produces `NaN` for some pairs of values, then `comparefn` is never a "consistent comparison function" (as defined in Section 22.1.3.24 Array.prototype.sort), and thus the behaviour of sort is still allowed to be "implementation-defined".

But actually, we are not interested whether `comparefn` is a consistent comparison function, but whether SortCompare (defined in Section 22.1.3.24.1 Runtime Semantics: SortCompare Abstract Operation) is "consistent".

However, since the change made in Rev.26, it is no longer the same thing for SortCompare or for `comparefn` to be consistent...

I think that the more elegant way to resolve the issue is as follows:

* Revert the change made in Rev. 26; that is, in the abstract operation SortCompare, remove the special-casing for NaN. That will effectively remove the discrepancy between the "consistence" of `comparefn` and the "consistence" of SortCompare.

* Change the definition of "consistent comparison function" by allowing NaN to denote the "equality"; more precisely, make the following changes in the text:

* "a =CF b means comparefn(a,b) = 0 (of either sign)"
==> "a =CF b means comparefn(a,b) is +0, -0, or NaN"

* "Furthermore, Type(v) is Number, and v is not NaN."
==> "Furthermore, Type(v) is Number."


In fact, the objection of Comment #5 may be applied to further cases, e.g. when the `compareFn` does not produce values of type Number. In that case, implementations have also a more well-defined behaviour than what is currently specced; see Bug #3137.

I'm reclosing this Bug because of that, and because it is superseded by Bug #3137. In case I'm finding a convenient formulation for "consistent" that handles more cases than "non-NaN numbers", I could open a new Bug.