Sort Without A Comparator
ID |
javascript.sort_without_comparator |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
JavaScript |
Tags |
collections, correctness, reliability |
Description
Reports .sort() or .toSorted() called with no comparator on an array of numbers.
The default order is not numeric. The specification converts every element to a string and compares the strings, so [10, 9, 1].sort() answers [1, 10, 9].
Reported only where the source says the elements are numbers: the receiver is an array literal of numeric literals, or a variable or parameter declared with one of those or annotated number[], bigint[] or Array<number>. That restriction is correctness rather than caution — the default order is the right one for an array of strings, so reporting ['b', 'a'].sort() would be a false positive.
The receiver is resolved through the symbol table, so only a declaration in the same file answers. A later reassignment is not followed, and neither is a receiver reached through a longer path such as report.rows.sort().
Related: javascript.return_value_ignored already reports a discarded toSorted() result, since that method is pure. This rule is about the missing comparator and fires whether or not the result is used.
Rationale
// Bad
const sizes = [10, 9, 1];
sizes.sort(); // [1, 10, 9]
-
On single-digit data the string order and the numeric order agree, so the code passes review, passes its tests and ships.
-
The wrong order appears the first time a value reaches two digits — in a chart axis, a "top ten" list, a paginated table — far from the line that caused it.
-
There is no error to follow: the array is sorted, just not the way the author meant, so the symptom is a wrong number on a screen rather than a stack trace.
-
sortmutates in place, so every later reader of the same array inherits the wrong order.