diff --git a/packages/ember-runtime/lib/mixins/array.js b/packages/ember-runtime/lib/mixins/array.js index 4beafe4a098..9d931333bd0 100644 --- a/packages/ember-runtime/lib/mixins/array.js +++ b/packages/ember-runtime/lib/mixins/array.js @@ -142,20 +142,22 @@ export function arrayContentDidChange(array, startIdx, removeAmt, addAmt) { let meta = peekMeta(array); let cache = meta && meta.readableCache(); if (cache !== undefined) { - if (cache.firstObject !== undefined && startIdx === 0) { + let length = get(array, 'length'); + let addedAmount = (addAmt === -1 ? 0 : addAmt); + let removedAmount = (removeAmt === -1 ? 0 : removeAmt); + let delta = addedAmount - removedAmount; + let previousLength = length - delta; + + let normalStartIdx = startIdx < 0 ? previousLength + startIdx : startIdx; + if (cache.firstObject !== undefined && normalStartIdx === 0) { propertyWillChange(array, 'firstObject'); propertyDidChange(array, 'firstObject'); } if (cache.lastObject !== undefined) { - let addedAmount = (addAmt === -1 ? 0 : addAmt); - let removedAmount = (removeAmt === -1 ? 0 : removeAmt); - let delta = addedAmount - removedAmount; - let length = get(array, 'length'); - - let lastIndex = length - delta - 1; - let lastAffectedIndex = startIdx + removedAmount; - if (lastIndex < lastAffectedIndex) { + let previousLastIndex = previousLength - 1; + let lastAffectedIndex = normalStartIdx + removedAmount; + if (previousLastIndex < lastAffectedIndex) { propertyWillChange(array, 'lastObject'); propertyDidChange(array, 'lastObject'); } diff --git a/packages/ember-runtime/tests/suites/mutable_array/replace.js b/packages/ember-runtime/tests/suites/mutable_array/replace.js index b9f17b08484..7823f510cb2 100644 --- a/packages/ember-runtime/tests/suites/mutable_array/replace.js +++ b/packages/ember-runtime/tests/suites/mutable_array/replace.js @@ -126,6 +126,28 @@ suite.test('[A,B,C,D].replace(2,2) => [A,B] + notify', function() { equal(observer.validate('firstObject'), false, 'should NOT have notified firstObject once'); }); +suite.test('[A,B,C,D].replace(-1,1) => [A,B,C] + notify', function() { + let before = this.newFixture(4); + let after = [before[0], before[1], before[2]]; + + let obj = this.newObject(before); + let observer = this.newObserver(obj, '[]', '@each', 'length', 'firstObject', 'lastObject'); + + obj.getProperties('firstObject', 'lastObject'); /* Prime the cache */ + + obj.replace(-1, 1); + + deepEqual(this.toArray(obj), after, 'post item results'); + + equal(observer.timesCalled('[]'), 1, 'should have notified [] once'); + equal(observer.timesCalled('@each'), 0, 'should not have notified @each once'); + equal(observer.timesCalled('length'), 1, 'should have notified length once'); + equal(observer.timesCalled('lastObject'), 1, 'should have notified lastObject once'); + + equal(observer.validate('firstObject'), false, 'should NOT have notified firstObject once'); +}); + + suite.test('Adding object should notify enumerable observer', function() { let fixtures = this.newFixture(4); let obj = this.newObject(fixtures);