diff --git a/src/ng/compile.js b/src/ng/compile.js index cff8fb38516c..e5e430d76c0a 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -1177,7 +1177,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { var clone = transcludeFn(transcludedScope, cloneFn, controllers, previousBoundTranscludeFn, futureParentElement); if (scopeCreated && !elementTransclusion) { - clone.on('$destroy', function() { transcludedScope.$destroy(); }); + futureParentElement.on('$destroy', function() { transcludedScope.$destroy(); }); } return clone; }; diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index 2a0d84d04150..7c3f8397db1f 100755 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -5551,6 +5551,64 @@ describe('$compile', function() { }); }); + + it('should not leak memory when a directive removes the element containing the transclude directive', function() { + + module(function() { + directive('toggle', function() { + return { + transclude: true, + template: + '
' + + '
' + + '
' + + '
' + + '
' + }; + }); + }); + + inject(function($compile, $rootScope) { + + function getAllScopes() { + return [$rootScope].concat( + getChildScopes($rootScope) + ); + + function getChildScopes(scope) { + var children = []; + if (!scope.$$childHead) { return children; } + var childScope = scope.$$childHead; + do { + children.push(childScope); + children = children.concat(getChildScopes(childScope)); + } while ((childScope = childScope.$$nextSibling)); + return children; + } + } + + $rootScope.messages = ['message 0']; + + element = $compile( + '
' + + '
{{ message }}
' + + '
' + )($rootScope); + + $rootScope.$apply('t = true'); + expect(element.text()).toContain('message 0'); + expect(getAllScopes().length).toEqual(4); + $rootScope.$apply('t = false'); + expect(element.text()).not.toContain('message 0'); + expect(getAllScopes().length).toEqual(1); + $rootScope.$apply('t = true'); + expect(element.text()).toContain('message 0'); + expect(getAllScopes().length).toEqual(4); + $rootScope.$apply('t = false'); + expect(element.text()).not.toContain('message 0'); + expect(getAllScopes().length).toEqual(1); + }); + }); });