diff --git a/lib/component.js b/lib/component.js index 62c8b550..1ccd1540 100644 --- a/lib/component.js +++ b/lib/component.js @@ -27,7 +27,11 @@ define( componentInfo && Object.keys(componentInfo.instances).forEach(function(k) { var info = componentInfo.instances[k]; - info.instance.teardown(); + // It's possible that a previous teardown caused another component to teardown, + // so we can't assume that the instances object is as it was. + if (info && info.instance) { + info.instance.teardown(); + } }); } diff --git a/test/spec/constructor_spec.js b/test/spec/constructor_spec.js index 1295edc5..28de4959 100644 --- a/test/spec/constructor_spec.js +++ b/test/spec/constructor_spec.js @@ -108,5 +108,34 @@ define(['lib/component'], function (defineComponent) { }).toThrow('utils.push attempted to overwrite "core" while running in protected mode'); }); + describe('teardownAll', function () { + + it('should teardown all instances', function () { + var TestComponent = defineComponent(testComponent); + var instance1 = (new TestComponent).initialize(document.body) + var instance2 = (new TestComponent).initialize(document.body); + spyOn(instance1, 'teardown').andCallThrough(); + spyOn(instance2, 'teardown').andCallThrough(); + TestComponent.teardownAll(); + expect(instance1.teardown).toHaveBeenCalled(); + expect(instance2.teardown).toHaveBeenCalled(); + }); + + it('should support teardowns that cause other teardowns', function () { + var TestComponent = defineComponent(testComponent); + var instance1 = (new TestComponent).initialize(document.body) + var instance2 = (new TestComponent).initialize(document.body); + var original = instance1.teardown; + instance1.teardown = function () { + instance2.teardown(); + original.call(this); + }.bind(instance1); + expect(function () { + TestComponent.teardownAll(); + }).not.toThrow(); + }); + + }); + }); });