From fe5f585c507b8c26a0983bacc801c6c6e4c7d529 Mon Sep 17 00:00:00 2001 From: BobChao87 Date: Sun, 14 May 2017 23:09:17 -0700 Subject: [PATCH] fix(orderBy): gaurantee stable sort If user-provided comparison function fails to differentiate between two elements, fall back to built-in comparator. Fixes #14881 --- src/ng/filter/orderBy.js | 7 +++---- test/ng/filter/orderBySpec.js | 13 +++++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/ng/filter/orderBy.js b/src/ng/filter/orderBy.js index 6b353b62d623..14805ab16420 100644 --- a/src/ng/filter/orderBy.js +++ b/src/ng/filter/orderBy.js @@ -49,9 +49,8 @@ * second, or `1` otherwise. * * In order to ensure that the sorting will be deterministic across platforms, if none of the - * specified predicates can distinguish between two items, `orderBy` will automatically introduce a - * 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.) + * specified predicates nor the custom comparator can distinguish between two items, `orderBy` will + * automatically introduce a dummy predicate that returns the item's index as `value`. * * 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 @@ -599,7 +598,7 @@ function orderByFilter($parse) { } } - return compare(v1.tieBreaker, v2.tieBreaker) * descending; + return (compare(v1.tieBreaker, v2.tieBreaker) || defaultCompare(v1.tieBreaker, v2.tieBreaker)) * descending; } }; diff --git a/test/ng/filter/orderBySpec.js b/test/ng/filter/orderBySpec.js index c9513d534156..e8f0a4126eff 100644 --- a/test/ng/filter/orderBySpec.js +++ b/test/ng/filter/orderBySpec.js @@ -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() {