diff --git a/packages/ember-runtime/lib/mixins/array.js b/packages/ember-runtime/lib/mixins/array.js index 1fe9f3ae821..fcb62289990 100644 --- a/packages/ember-runtime/lib/mixins/array.js +++ b/packages/ember-runtime/lib/mixins/array.js @@ -141,19 +141,24 @@ export function arrayContentDidChange(array, startIdx, removeAmt, addAmt) { let meta = peekMeta(array); let cache = meta && meta.readableCache(); - - if (cache) { - if (cache.firstObject !== undefined && - objectAt(array, 0) !== cacheFor.get(cache, 'firstObject')) { - propertyWillChange(array, 'firstObject', meta); - propertyDidChange(array, 'firstObject', meta); - } - if (cache.lastObject !== undefined && - objectAt(array, get(array, 'length') - 1) !== cacheFor.get(cache, 'lastObject')) { - propertyWillChange(array, 'lastObject', meta); - propertyDidChange(array, 'lastObject', meta); + if (cache !== undefined) { + if (cache.firstObject !== undefined && startIdx === 0 && objectAt(array, 0) !== cacheFor.get(cache, 'firstObject')) { + propertyWillChange(array, 'firstObject'); + propertyDidChange(array, 'firstObject'); } + + if (cache.lastObject !== undefined) { + let delta = (addAmt === -1 ? 0 : addAmt) - (removeAmt === -1 ? 0 : removeAmt); + let length = get(array, 'length'); + + let lastIndex = length - delta - 1; + if ((lastIndex === -1 || delta === 0 || !(startIdx < lastIndex && lastIndex < length)) && objectAt(array, length - 1) !== cacheFor.get(cache, 'lastObject')) { + propertyWillChange(array, 'lastObject'); + propertyDidChange(array, 'lastObject'); + } + } } + return array; } diff --git a/packages/ember-runtime/tests/suites/mutable_array/insertAt.js b/packages/ember-runtime/tests/suites/mutable_array/insertAt.js index be4e4de840b..eb230c160b6 100644 --- a/packages/ember-runtime/tests/suites/mutable_array/insertAt.js +++ b/packages/ember-runtime/tests/suites/mutable_array/insertAt.js @@ -135,10 +135,20 @@ suite.test('[A,B,C].insertAt(1,X) => [A,X,B,C] + notify', function() { let after = [before[0], item, before[1], before[2]]; let obj = this.newObject(before); let observer = this.newObserver(obj, '[]', '@each', 'length', 'firstObject', 'lastObject'); + let objectAtCalls = []; + + let objectAt = obj.objectAt; + obj.objectAt = (ix) => { + objectAtCalls.push(ix); + return objectAt.call(obj, ix); + } obj.getProperties('firstObject', 'lastObject'); /* Prime the cache */ + objectAtCalls.splice(0, objectAtCalls.length); + obj.insertAt(1, item); + deepEqual(objectAtCalls, [], 'objectAt is not called when only inserting items'); deepEqual(this.toArray(obj), after, 'post item results'); equal(get(obj, 'length'), after.length, 'length');