fix(orderBy): guarantee stable sort
If a user-provided comparator fails to differentiate between two items, fall back to the built-in comparator (using the tie-breaker predicate). Fixes #14881 Closes #15914
This commit is contained in:
committed by
Georgios Kalpakas
parent
a86a3195b4
commit
762580ff34
@@ -53,6 +53,9 @@
|
||||
* dummy predicate that returns the item's index as `value`.
|
||||
* (If you are using a custom comparator, make sure it can handle this predicate as well.)
|
||||
*
|
||||
* If a custom comparator still can't distinguish between two items, then they will be sorted based
|
||||
* on their index using the built-in comparator.
|
||||
*
|
||||
* Finally, in an attempt to simplify things, if a predicate returns an object as the extracted
|
||||
* value for an item, `orderBy` will try to convert that object to a primitive value, before passing
|
||||
* it to the comparator. The following rules govern the conversion:
|
||||
@@ -599,7 +602,7 @@ function orderByFilter($parse) {
|
||||
}
|
||||
}
|
||||
|
||||
return compare(v1.tieBreaker, v2.tieBreaker) * descending;
|
||||
return (compare(v1.tieBreaker, v2.tieBreaker) || defaultCompare(v1.tieBreaker, v2.tieBreaker)) * descending;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -457,6 +457,19 @@ describe('Filter: orderBy', function() {
|
||||
|
||||
expect(orderBy(items, expr, reverse, comparator)).toEqual(sorted);
|
||||
});
|
||||
|
||||
it('should use the default comparator to break ties on a provided comparator', function() {
|
||||
// Some list that won't be sorted "naturally", i.e. should sort to ['a', 'B', 'c']
|
||||
var items = ['c', 'a', 'B'];
|
||||
var expr = null;
|
||||
function comparator() {
|
||||
return 0;
|
||||
}
|
||||
var reversed = ['B', 'a', 'c'];
|
||||
|
||||
expect(orderBy(items, expr, false, comparator)).toEqual(items);
|
||||
expect(orderBy(items, expr, true, comparator)).toEqual(reversed);
|
||||
});
|
||||
});
|
||||
|
||||
describe('(object as `value`)', function() {
|
||||
|
||||
Reference in New Issue
Block a user