diff --git a/packages/ember-runtime/lib/compare.js b/packages/ember-runtime/lib/compare.js index ac668e95935..a32dc89b82d 100644 --- a/packages/ember-runtime/lib/compare.js +++ b/packages/ember-runtime/lib/compare.js @@ -109,7 +109,18 @@ export default function compare(v, w) { return spaceship(v, w); case 'string': - return spaceship(v.localeCompare(w), 0); + // We are comparing Strings using operators instead of `String#localeCompare` + // because of unexpected behavior for certain edge cases. + // For example `'Z'.localeCompare('a')` returns `1`. + // + // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare#Description + if (v < w) { + return -1; + } else if (v === w) { + return 0; + } + + return 1; case 'array': var vLen = v.length; diff --git a/packages/ember-runtime/tests/core/compare_test.js b/packages/ember-runtime/tests/core/compare_test.js index 0f8a6bc4200..f1ba17f2d89 100644 --- a/packages/ember-runtime/tests/core/compare_test.js +++ b/packages/ember-runtime/tests/core/compare_test.js @@ -74,4 +74,8 @@ QUnit.test('comparables should return values in the range of -1, 0, 1', function equal(compare('a', negOne), 1, 'Second item comparable - returns -1 (negated)'); equal(compare('b', zero), 0, 'Second item comparable - returns 0 (negated)'); equal(compare('c', one), -1, 'Second item comparable - returns 1 (negated)'); + + equal(compare('A', 'Z'), -1, `'A' < 'Z' returns -1`); + equal(compare('Z', 'a'), -1, `'Z' < 'a' returns -1`); + equal(compare('a', 'z'), -1, `'a' < 'z' returns -1`); });