From 964e2da7589d11ce5def1f128109560da978aa16 Mon Sep 17 00:00:00 2001 From: Caitlin Potter Date: Wed, 3 Dec 2014 12:59:41 -0500 Subject: [PATCH 1/2] fix(orderBy): maintain order in array of objects when predicate is not provided In ES262, there are two properties which are used to get a primitive value from an Object: - valueOf() -- a method which returns a primitive value represented by the Object - toString() -- a method which returns a string value representing the Object. When comparing objects using relational operators, the abstract operation ToPrimitive(O, TypeHint) is used, which will use these methods to retrieve a value. This CL emulates the behaviour of ToPrimitive(), and ensures that no ordering occurs if the retrieved value is identical. This behaviour was previously used for Date objects, however it can be safely made generic as it applies to all objects. Closes #9566 Closes #9747 --- src/ng/filter/orderBy.js | 15 ++++++++++----- test/ng/filter/orderBySpec.js | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/ng/filter/orderBy.js b/src/ng/filter/orderBy.js index 3659c55a2e99..5b232632fd2a 100644 --- a/src/ng/filter/orderBy.js +++ b/src/ng/filter/orderBy.js @@ -163,12 +163,17 @@ function orderByFilter($parse) { function compare(v1, v2) { var t1 = typeof v1; var t2 = typeof v2; - if (t1 == t2) { - if (isDate(v1) && isDate(v2)) { - v1 = v1.valueOf(); - v2 = v2.valueOf(); + if (t1 === t2 && t1 === "object") { + t1 = typeof (v1 = v1.valueOf()); + t2 = typeof (v2 = v2.valueOf()); + if (t1 === t2 && t1 === "object") { + t1 = typeof (v1 = v1.toString()); + t2 = typeof (v2 = v2.toString()); + if (t1 === t2 && v1 === v2) return 0; } - if (t1 == "string") { + } + if (t1 === t2) { + if (t1 === "string") { v1 = v1.toLowerCase(); v2 = v2.toLowerCase(); } diff --git a/test/ng/filter/orderBySpec.js b/test/ng/filter/orderBySpec.js index 788f145fd1e0..11eec4329403 100644 --- a/test/ng/filter/orderBySpec.js +++ b/test/ng/filter/orderBySpec.js @@ -104,6 +104,17 @@ describe('Filter: orderBy', function() { return orderBy([{"Tip %": .15}, {"Tip %": .25}, {"Tip %": .40}], '"Tip %\''); }).toThrow(); }); + + + it('should not reverse array of objects with no predicate', function() { + var array = [ + { id: 2 }, + { id: 1 }, + { id: 4 }, + { id: 3 } + ]; + expect(orderBy(array)).toEqualData(array); + }); }); @@ -210,5 +221,16 @@ describe('Filter: orderBy', function() { return orderBy([{"Tip %": .15}, {"Tip %": .25}, {"Tip %": .40}], '"Tip %\''); }).toThrow(); }); + + + it('should not reverse array of objects with no predicate', function() { + var array = [ + { id: 2 }, + { id: 1 }, + { id: 4 }, + { id: 3 } + ]; + expect(orderBy(array)).toEqualData(array); + }); }); }); From e4eabb5de31234bd1d875a144b065076dab30594 Mon Sep 17 00:00:00 2001 From: Caitlin Potter Date: Wed, 3 Dec 2014 13:34:49 -0500 Subject: [PATCH 2/2] fix(orderBy): make object-to-primtiive behaviour work for objects with null prototype --- src/ng/filter/orderBy.js | 10 +++++----- test/ng/filter/orderBySpec.js | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/ng/filter/orderBy.js b/src/ng/filter/orderBy.js index 5b232632fd2a..42c8e1280f7e 100644 --- a/src/ng/filter/orderBy.js +++ b/src/ng/filter/orderBy.js @@ -164,12 +164,12 @@ function orderByFilter($parse) { var t1 = typeof v1; var t2 = typeof v2; if (t1 === t2 && t1 === "object") { - t1 = typeof (v1 = v1.valueOf()); - t2 = typeof (v2 = v2.valueOf()); + t1 = typeof (v1.valueOf ? v1 = v1.valueOf() : v1); + t2 = typeof (v2.valueOf ? v2 = v2.valueOf() : v2); if (t1 === t2 && t1 === "object") { - t1 = typeof (v1 = v1.toString()); - t2 = typeof (v2 = v2.toString()); - if (t1 === t2 && v1 === v2) return 0; + t1 = typeof (v1.toString ? v1 = v1.toString() : v1); + t2 = typeof (v2.toString ? v2 = v2.toString() : v2); + if (t1 === t2 && v1 === v2 || t1 === "object") return 0; } } if (t1 === t2) { diff --git a/test/ng/filter/orderBySpec.js b/test/ng/filter/orderBySpec.js index 11eec4329403..8380b7a048c2 100644 --- a/test/ng/filter/orderBySpec.js +++ b/test/ng/filter/orderBySpec.js @@ -115,6 +115,16 @@ describe('Filter: orderBy', function() { ]; expect(orderBy(array)).toEqualData(array); }); + + + it('should not reverse array of objects with null prototype and no predicate', function() { + var array = [2,1,4,3].map(function(id) { + var obj = Object.create(null); + obj.id = id; + return obj; + }); + expect(orderBy(array)).toEqualData(array); + }); }); @@ -232,5 +242,15 @@ describe('Filter: orderBy', function() { ]; expect(orderBy(array)).toEqualData(array); }); + + + it('should not reverse array of objects with null prototype and no predicate', function() { + var array = [2,1,4,3].map(function(id) { + var obj = Object.create(null); + obj.id = id; + return obj; + }); + expect(orderBy(array)).toEqualData(array); + }); }); });