{"action":"created","comment":{"url":"https://api.github.com/repos/emberjs/ember.js/pulls/comments/33995673","id":33995673,"diff_hunk":"@@ -68,3 +69,41 @@ QUnit.test('should not duplicate childViews when rerendering', function() {\n     outerView.destroy();\n   });\n });\n+\n+QUnit.test('should remove childViews on destroy', function() {\n+  var outerView = EmberView.extend({\n+    component: 'my-thing',\n+    value: false,\n+    container: {\n+      lookup() {\n+        return {\n+          componentFor(tagName, container) {\n+            return Component.extend({\n+              destroy() {","path":"packages/ember-views/tests/views/view/child_views_test.js","position":21,"original_position":21,"commit_id":"c9c4874d63985fc2c28a5472ac9d8689acc52ef5","original_commit_id":"c9c4874d63985fc2c28a5472ac9d8689acc52ef5","user":{"login":"igorT","id":715175,"avatar_url":"https://avatars.githubusercontent.com/u/715175?v=3","gravatar_id":"","url":"https://api.github.com/users/igorT","html_url":"https://github.com/igorT","followers_url":"https://api.github.com/users/igorT/followers","following_url":"https://api.github.com/users/igorT/following{/other_user}","gists_url":"https://api.github.com/users/igorT/gists{/gist_id}","starred_url":"https://api.github.com/users/igorT/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/igorT/subscriptions","organizations_url":"https://api.github.com/users/igorT/orgs","repos_url":"https://api.github.com/users/igorT/repos","events_url":"https://api.github.com/users/igorT/events{/privacy}","received_events_url":"https://api.github.com/users/igorT/received_events","type":"User","site_admin":false},"body":"Why do we need this?","created_at":"2015-07-06T23:48:12Z","updated_at":"2015-07-06T23:48:12Z","html_url":"https://github.com/emberjs/ember.js/pull/11667#discussion_r33995673","pull_request_url":"https://api.github.com/repos/emberjs/ember.js/pulls/11667","_links":{"self":{"href":"https://api.github.com/repos/emberjs/ember.js/pulls/comments/33995673"},"html":{"href":"https://github.com/emberjs/ember.js/pull/11667#discussion_r33995673"},"pull_request":{"href":"https://api.github.com/repos/emberjs/ember.js/pulls/11667"}}},"pull_request":{"url":"https://api.github.com/repos/emberjs/ember.js/pulls/11667","id":39322418,"html_url":"https://github.com/emberjs/ember.js/pull/11667","diff_url":"https://github.com/emberjs/ember.js/pull/11667.diff","patch_url":"https://github.com/emberjs/ember.js/pull/11667.patch","issue_url":"https://api.github.com/repos/emberjs/ember.js/issues/11667","number":11667,"state":"open","locked":false,"title":"[BUGFIX release] Fix Glimmer memory leak","user":{"login":"tomdale","id":90888,"avatar_url":"https://avatars.githubusercontent.com/u/90888?v=3","gravatar_id":"","url":"https://api.github.com/users/tomdale","html_url":"https://github.com/tomdale","followers_url":"https://api.github.com/users/tomdale/followers","following_url":"https://api.github.com/users/tomdale/following{/other_user}","gists_url":"https://api.github.com/users/tomdale/gists{/gist_id}","starred_url":"https://api.github.com/users/tomdale/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tomdale/subscriptions","organizations_url":"https://api.github.com/users/tomdale/orgs","repos_url":"https://api.github.com/users/tomdale/repos","events_url":"https://api.github.com/users/tomdale/events{/privacy}","received_events_url":"https://api.github.com/users/tomdale/received_events","type":"User","site_admin":false},"body":"This commit resolves a memory leak (#11501) in apps running Glimmer. The root cause of the issue was that a flag governing whether components/views remove themselves from their parent was being set incorrectly, so that when the code to cleanup a destroyed view ran, it was not removed from its parent’s `childViews` array.\r\n\r\nSpecifically, three hooks are invoked when a render node is cleared:\r\n\r\n  1. `env.hooks.willCleanupNode`\r\n  2. `Morph#cleanup`\r\n  3. `env.hooks.didCleanupNode`\r\n\r\nPrior to this commit, `willCleanupNode` would blindly set the owner view’s `isDestroyingSubtree` flag if there was a view set in the `env` (i.e., basically always).\r\n\r\nSidebar on the `isDestroyingSubtree` flag: this flag is used as a performance optimization. If a view is destroyed, we want to remove that view from its parent’s `childViews` array so that garbage collection can happen. However, it is unnecessary to remove child views from the destroyed view’s `childViews` array; the GC will take care of any clean up when the link between the view hierarchy and the destroyed view is severed.\r\n\r\nFor example, imagine this hypothetical view hierarchy:\r\n\r\n```\r\n      A\r\n     / \\\r\n    B   C\r\n       / \\\r\n      D   E\r\n```\r\n\r\nIf the render node for view C is destroyed, we need to remove C from A’s array of child views. However, it is unnecessary to remove D or E from C’s child views, because they will be imminently removed by the GC, and temporarily lingering in the child views array does no harm.\r\n\r\nWe accomplish this by setting the `isDestroyingSubtree` flag on the root-most view in a hierarchy (view A in the example above), which we call the owner view. When the render node for C is destroyed, it removes C from A’s child views array and sets the flag to true. When D and E’s render nodes are destroyed, they see that the flag has already been flipped and do not remove their associated views from C’s child views array.\r\n\r\nThe memory leak manifested itself when the a render node that did not have a view associated with it was destroyed, and contained a child render node that _did_ have a view associated. For example:\r\n\r\n```handlebars\r\n{{#if foo}}\r\n  {{my-component}}\r\n{{/if}}\r\n```\r\n\r\nIn this case, the `willCleanupNode` hook would erroneously set the flag without actually moving the `my-component` view, because the render node for the `{{if}}` does not know about the component.\r\n\r\nWhen the cleanup for `{{my-component}}` finally happens (in Morph#cleanup), the flag has already been set, so the render node incorrectly assumes that its view is part of a subgraph that has already been severed.\r\n\r\nAs far as we can tell, the `willCleanupNode` hook is not doing any cleanup that is not already done in `Morph#cleanup`. We still do need `didCleanupNode` to clear the flag, but can leave individual render node cleanup to the render node itself.","created_at":"2015-07-06T23:43:44Z","updated_at":"2015-07-06T23:48:12Z","closed_at":null,"merged_at":null,"merge_commit_sha":"e4e40eb23a0e9f28f3c2ca4c69f779916ef9035e","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/emberjs/ember.js/pulls/11667/commits","review_comments_url":"https://api.github.com/repos/emberjs/ember.js/pulls/11667/comments","review_comment_url":"https://api.github.com/repos/emberjs/ember.js/pulls/comments{/number}","comments_url":"https://api.github.com/repos/emberjs/ember.js/issues/11667/comments","statuses_url":"https://api.github.com/repos/emberjs/ember.js/statuses/c9c4874d63985fc2c28a5472ac9d8689acc52ef5","head":{"label":"emberjs:stefanpenner-memory-leak","ref":"stefanpenner-memory-leak","sha":"c9c4874d63985fc2c28a5472ac9d8689acc52ef5","user":{"login":"emberjs","id":1253363,"avatar_url":"https://avatars.githubusercontent.com/u/1253363?v=3","gravatar_id":"","url":"https://api.github.com/users/emberjs","html_url":"https://github.com/emberjs","followers_url":"https://api.github.com/users/emberjs/followers","following_url":"https://api.github.com/users/emberjs/following{/other_user}","gists_url":"https://api.github.com/users/emberjs/gists{/gist_id}","starred_url":"https://api.github.com/users/emberjs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/emberjs/subscriptions","organizations_url":"https://api.github.com/users/emberjs/orgs","repos_url":"https://api.github.com/users/emberjs/repos","events_url":"https://api.github.com/users/emberjs/events{/privacy}","received_events_url":"https://api.github.com/users/emberjs/received_events","type":"Organization","site_admin":false},"repo":{"id":1801829,"name":"ember.js","full_name":"emberjs/ember.js","owner":{"login":"emberjs","id":1253363,"avatar_url":"https://avatars.githubusercontent.com/u/1253363?v=3","gravatar_id":"","url":"https://api.github.com/users/emberjs","html_url":"https://github.com/emberjs","followers_url":"https://api.github.com/users/emberjs/followers","following_url":"https://api.github.com/users/emberjs/following{/other_user}","gists_url":"https://api.github.com/users/emberjs/gists{/gist_id}","starred_url":"https://api.github.com/users/emberjs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/emberjs/subscriptions","organizations_url":"https://api.github.com/users/emberjs/orgs","repos_url":"https://api.github.com/users/emberjs/repos","events_url":"https://api.github.com/users/emberjs/events{/privacy}","received_events_url":"https://api.github.com/users/emberjs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/emberjs/ember.js","description":"Ember.js - A JavaScript framework for creating ambitious web applications","fork":false,"url":"https://api.github.com/repos/emberjs/ember.js","forks_url":"https://api.github.com/repos/emberjs/ember.js/forks","keys_url":"https://api.github.com/repos/emberjs/ember.js/keys{/key_id}","collaborators_url":"https://api.github.com/repos/emberjs/ember.js/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/emberjs/ember.js/teams","hooks_url":"https://api.github.com/repos/emberjs/ember.js/hooks","issue_events_url":"https://api.github.com/repos/emberjs/ember.js/issues/events{/number}","events_url":"https://api.github.com/repos/emberjs/ember.js/events","assignees_url":"https://api.github.com/repos/emberjs/ember.js/assignees{/user}","branches_url":"https://api.github.com/repos/emberjs/ember.js/branches{/branch}","tags_url":"https://api.github.com/repos/emberjs/ember.js/tags","blobs_url":"https://api.github.com/repos/emberjs/ember.js/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/emberjs/ember.js/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/emberjs/ember.js/git/refs{/sha}","trees_url":"https://api.github.com/repos/emberjs/ember.js/git/trees{/sha}","statuses_url":"https://api.github.com/repos/emberjs/ember.js/statuses/{sha}","languages_url":"https://api.github.com/repos/emberjs/ember.js/languages","stargazers_url":"https://api.github.com/repos/emberjs/ember.js/stargazers","contributors_url":"https://api.github.com/repos/emberjs/ember.js/contributors","subscribers_url":"https://api.github.com/repos/emberjs/ember.js/subscribers","subscription_url":"https://api.github.com/repos/emberjs/ember.js/subscription","commits_url":"https://api.github.com/repos/emberjs/ember.js/commits{/sha}","git_commits_url":"https://api.github.com/repos/emberjs/ember.js/git/commits{/sha}","comments_url":"https://api.github.com/repos/emberjs/ember.js/comments{/number}","issue_comment_url":"https://api.github.com/repos/emberjs/ember.js/issues/comments{/number}","contents_url":"https://api.github.com/repos/emberjs/ember.js/contents/{+path}","compare_url":"https://api.github.com/repos/emberjs/ember.js/compare/{base}...{head}","merges_url":"https://api.github.com/repos/emberjs/ember.js/merges","archive_url":"https://api.github.com/repos/emberjs/ember.js/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/emberjs/ember.js/downloads","issues_url":"https://api.github.com/repos/emberjs/ember.js/issues{/number}","pulls_url":"https://api.github.com/repos/emberjs/ember.js/pulls{/number}","milestones_url":"https://api.github.com/repos/emberjs/ember.js/milestones{/number}","notifications_url":"https://api.github.com/repos/emberjs/ember.js/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/emberjs/ember.js/labels{/name}","releases_url":"https://api.github.com/repos/emberjs/ember.js/releases{/id}","created_at":"2011-05-25T23:39:40Z","updated_at":"2015-07-06T20:37:52Z","pushed_at":"2015-07-06T23:47:42Z","git_url":"git://github.com/emberjs/ember.js.git","ssh_url":"git@github.com:emberjs/ember.js.git","clone_url":"https://github.com/emberjs/ember.js.git","svn_url":"https://github.com/emberjs/ember.js","homepage":"http://www.emberjs.com","size":81746,"stargazers_count":14177,"watchers_count":14177,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":3038,"mirror_url":null,"open_issues_count":532,"forks":3038,"open_issues":532,"watchers":14177,"default_branch":"master"}},"base":{"label":"emberjs:master","ref":"master","sha":"1dcd65220251ff524651a037aa0af4c6fd715275","user":{"login":"emberjs","id":1253363,"avatar_url":"https://avatars.githubusercontent.com/u/1253363?v=3","gravatar_id":"","url":"https://api.github.com/users/emberjs","html_url":"https://github.com/emberjs","followers_url":"https://api.github.com/users/emberjs/followers","following_url":"https://api.github.com/users/emberjs/following{/other_user}","gists_url":"https://api.github.com/users/emberjs/gists{/gist_id}","starred_url":"https://api.github.com/users/emberjs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/emberjs/subscriptions","organizations_url":"https://api.github.com/users/emberjs/orgs","repos_url":"https://api.github.com/users/emberjs/repos","events_url":"https://api.github.com/users/emberjs/events{/privacy}","received_events_url":"https://api.github.com/users/emberjs/received_events","type":"Organization","site_admin":false},"repo":{"id":1801829,"name":"ember.js","full_name":"emberjs/ember.js","owner":{"login":"emberjs","id":1253363,"avatar_url":"https://avatars.githubusercontent.com/u/1253363?v=3","gravatar_id":"","url":"https://api.github.com/users/emberjs","html_url":"https://github.com/emberjs","followers_url":"https://api.github.com/users/emberjs/followers","following_url":"https://api.github.com/users/emberjs/following{/other_user}","gists_url":"https://api.github.com/users/emberjs/gists{/gist_id}","starred_url":"https://api.github.com/users/emberjs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/emberjs/subscriptions","organizations_url":"https://api.github.com/users/emberjs/orgs","repos_url":"https://api.github.com/users/emberjs/repos","events_url":"https://api.github.com/users/emberjs/events{/privacy}","received_events_url":"https://api.github.com/users/emberjs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/emberjs/ember.js","description":"Ember.js - A JavaScript framework for creating ambitious web applications","fork":false,"url":"https://api.github.com/repos/emberjs/ember.js","forks_url":"https://api.github.com/repos/emberjs/ember.js/forks","keys_url":"https://api.github.com/repos/emberjs/ember.js/keys{/key_id}","collaborators_url":"https://api.github.com/repos/emberjs/ember.js/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/emberjs/ember.js/teams","hooks_url":"https://api.github.com/repos/emberjs/ember.js/hooks","issue_events_url":"https://api.github.com/repos/emberjs/ember.js/issues/events{/number}","events_url":"https://api.github.com/repos/emberjs/ember.js/events","assignees_url":"https://api.github.com/repos/emberjs/ember.js/assignees{/user}","branches_url":"https://api.github.com/repos/emberjs/ember.js/branches{/branch}","tags_url":"https://api.github.com/repos/emberjs/ember.js/tags","blobs_url":"https://api.github.com/repos/emberjs/ember.js/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/emberjs/ember.js/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/emberjs/ember.js/git/refs{/sha}","trees_url":"https://api.github.com/repos/emberjs/ember.js/git/trees{/sha}","statuses_url":"https://api.github.com/repos/emberjs/ember.js/statuses/{sha}","languages_url":"https://api.github.com/repos/emberjs/ember.js/languages","stargazers_url":"https://api.github.com/repos/emberjs/ember.js/stargazers","contributors_url":"https://api.github.com/repos/emberjs/ember.js/contributors","subscribers_url":"https://api.github.com/repos/emberjs/ember.js/subscribers","subscription_url":"https://api.github.com/repos/emberjs/ember.js/subscription","commits_url":"https://api.github.com/repos/emberjs/ember.js/commits{/sha}","git_commits_url":"https://api.github.com/repos/emberjs/ember.js/git/commits{/sha}","comments_url":"https://api.github.com/repos/emberjs/ember.js/comments{/number}","issue_comment_url":"https://api.github.com/repos/emberjs/ember.js/issues/comments{/number}","contents_url":"https://api.github.com/repos/emberjs/ember.js/contents/{+path}","compare_url":"https://api.github.com/repos/emberjs/ember.js/compare/{base}...{head}","merges_url":"https://api.github.com/repos/emberjs/ember.js/merges","archive_url":"https://api.github.com/repos/emberjs/ember.js/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/emberjs/ember.js/downloads","issues_url":"https://api.github.com/repos/emberjs/ember.js/issues{/number}","pulls_url":"https://api.github.com/repos/emberjs/ember.js/pulls{/number}","milestones_url":"https://api.github.com/repos/emberjs/ember.js/milestones{/number}","notifications_url":"https://api.github.com/repos/emberjs/ember.js/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/emberjs/ember.js/labels{/name}","releases_url":"https://api.github.com/repos/emberjs/ember.js/releases{/id}","created_at":"2011-05-25T23:39:40Z","updated_at":"2015-07-06T20:37:52Z","pushed_at":"2015-07-06T23:47:42Z","git_url":"git://github.com/emberjs/ember.js.git","ssh_url":"git@github.com:emberjs/ember.js.git","clone_url":"https://github.com/emberjs/ember.js.git","svn_url":"https://github.com/emberjs/ember.js","homepage":"http://www.emberjs.com","size":81746,"stargazers_count":14177,"watchers_count":14177,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":3038,"mirror_url":null,"open_issues_count":532,"forks":3038,"open_issues":532,"watchers":14177,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/emberjs/ember.js/pulls/11667"},"html":{"href":"https://github.com/emberjs/ember.js/pull/11667"},"issue":{"href":"https://api.github.com/repos/emberjs/ember.js/issues/11667"},"comments":{"href":"https://api.github.com/repos/emberjs/ember.js/issues/11667/comments"},"review_comments":{"href":"https://api.github.com/repos/emberjs/ember.js/pulls/11667/comments"},"review_comment":{"href":"https://api.github.com/repos/emberjs/ember.js/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/emberjs/ember.js/pulls/11667/commits"},"statuses":{"href":"https://api.github.com/repos/emberjs/ember.js/statuses/c9c4874d63985fc2c28a5472ac9d8689acc52ef5"}}}}