diff --git a/src/ng/filter/orderBy.js b/src/ng/filter/orderBy.js index 3b4d11beb394..8ae08eb81dc6 100644 --- a/src/ng/filter/orderBy.js +++ b/src/ng/filter/orderBy.js @@ -160,29 +160,37 @@ function orderByFilter($parse) { ? function(a, b) {return comp(b,a);} : comp; } + + function isPrimitive(value) { + switch (typeof value) { + case 'number': /* falls through */ + case 'boolean': /* falls through */ + case 'string': + return true; + default: + return false; + } + } + + function objectToString(value) { + if (value === null) return 'null'; + if (typeof value.toString === 'function') { + value = value.toString(); + if (isPrimitive(value)) return value; + } + if (typeof value.valueOf === 'function') { + value = value.valueOf(); + if (isPrimitive(value)) return value; + } + return ''; + } + function compare(v1, v2) { var t1 = typeof v1; var t2 = typeof v2; - // Prepare values for Abstract Relational Comparison - // (http://www.ecma-international.org/ecma-262/5.1/#sec-11.8.5): - // If the resulting values are identical, return 0 to prevent - // incorrect re-ordering. if (t1 === t2 && t1 === "object") { - // If types are both numbers, emulate abstract ToPrimitive() operation - // in order to get primitive values suitable for comparison - t1 = typeof (v1.valueOf ? v1 = v1.valueOf() : v1); - t2 = typeof (v2.valueOf ? v2 = v2.valueOf() : v2); - if (t1 === t2 && t1 === "object") { - // Object.prototype.valueOf will return the original object, by - // default. If we do not receive a primitive value, use ToString() - // instead. - t1 = typeof (v1.toString ? v1 = v1.toString() : v1); - t2 = typeof (v2.toString ? v2 = v2.toString() : v2); - - // If the end result of toString() for each item is the same, do not - // perform relational comparison, and do not re-order objects. - if (t1 === t2 && v1 === v2 || t1 === "object") return 0; - } + v1 = objectToString(v1); + v2 = objectToString(v2); } if (t1 === t2) { if (t1 === "string") { diff --git a/test/ng/filter/orderBySpec.js b/test/ng/filter/orderBySpec.js index 8380b7a048c2..120425ba78ea 100644 --- a/test/ng/filter/orderBySpec.js +++ b/test/ng/filter/orderBySpec.js @@ -125,6 +125,22 @@ describe('Filter: orderBy', function() { }); expect(orderBy(array)).toEqualData(array); }); + + + it('should sort nulls as Array.prototype.sort', function() { + var array = [ + { id: 2 }, + null, + { id: 3 }, + null + ]; + expect(orderBy(array)).toEqualData([ + { id: 2 }, + { id: 3 }, + null, + null + ]); + }); }); @@ -252,5 +268,21 @@ describe('Filter: orderBy', function() { }); expect(orderBy(array)).toEqualData(array); }); + + + it('should sort nulls as Array.prototype.sort', function() { + var array = [ + { id: 2 }, + null, + { id: 3 }, + null + ]; + expect(orderBy(array)).toEqualData([ + { id: 2 }, + { id: 3 }, + null, + null + ]); + }); }); });