diff --git a/packages/ember-metal/lib/chains.js b/packages/ember-metal/lib/chains.js index 9da4e325819..334da9e26ee 100644 --- a/packages/ember-metal/lib/chains.js +++ b/packages/ember-metal/lib/chains.js @@ -287,9 +287,13 @@ ChainNode.prototype = { willChange(events) { var chains = this._chains; + var node; if (chains) { for (var key in chains) { - chains[key].willChange(events); + node = chains[key]; + if (node !== undefined) { + node.willChange(events); + } } } @@ -389,7 +393,10 @@ export function finishChains(obj) { chainNodes = chainWatchers[key]; if (chainNodes) { for (var i = 0, l = chainNodes.length; i < l; i++) { - chainNodes[i].didChange(null); + var node = chainNodes[i]; + if (node) { + node.didChange(null); + } } } } diff --git a/packages/ember-metal/tests/chains_test.js b/packages/ember-metal/tests/chains_test.js index 29405cc7b96..774b62c1472 100644 --- a/packages/ember-metal/tests/chains_test.js +++ b/packages/ember-metal/tests/chains_test.js @@ -1,6 +1,9 @@ import { addObserver } from 'ember-metal/observer'; +import { get } from 'ember-metal/property_get'; import { finishChains } from 'ember-metal/chains'; - +import { defineProperty } from 'ember-metal/properties'; +import computed from 'ember-metal/computed'; +import { propertyDidChange } from 'ember-metal/property_events'; QUnit.module('Chains'); QUnit.test('finishChains should properly copy chains from prototypes to instances', function() { @@ -14,3 +17,52 @@ QUnit.test('finishChains should properly copy chains from prototypes to instance ok(obj['__ember_meta__'].chains !== childObj['__ember_meta__'].chains, 'The chains object is copied'); }); + + +QUnit.test('observer and CP chains', function() { + var obj = { }; + + defineProperty(obj, 'foo', computed('qux.[]', function() { })); + defineProperty(obj, 'qux', computed(function() { })); + + // create DK chains + get(obj, 'foo'); + + // create observer chain + addObserver(obj, 'qux.length', function() { }); + + /* + +-----+ + | qux | root CP + +-----+ + ^ + +------+-----+ + | | + +--------+ +----+ + | length | | [] | chainWatchers + +--------+ +----+ + observer CP(foo, 'qux.[]') + */ + + + // invalidate qux + propertyDidChange(obj, 'qux'); + + // CP chain is blown away + + /* + +-----+ + | qux | root CP + +-----+ + ^ + +------+xxxxxx + | x + +--------+ xxxxxx + | length | x [] x chainWatchers + +--------+ xxxxxx + observer CP(foo, 'qux.[]') + */ + + get(obj, 'qux'); // CP chain re-recreated + ok(true, 'no crash'); +});