-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Track parent view of cleaned up render nodes
This commit fixes a bug where views created inside an `{{#each}}` were not getting removed appropriately from their parent’s `childViews` array when they were destroyed. Previously, we used a boolean flag to track whether we had removed the destroyed view from its parent. The first time we saw a view while walking the tree of destroyed render nodes, we should remove it from its parent view’s `childViews` and flip the flag to true. As we walked the tree, we assumed that any subsequent views were descendants of the root destroyed view, and therefore could be left in place while we waited for the GC to do its magic. However, the case we missed was when there were two sibling views being destroyed as part of the same root render node being cleaned up. For example, imagine this view graph: A / \ B /\ C D <— both created via an {{#each}} If the sibling views were inside a non-view-associated render node, and that render node was cleaned up (e.g., an {{#if}} that became falsy), the tree of nodes would be walked. Once it reached the render node associated with the C view, it would remove C from A’s `childViews` and toggle the flag to true, indicating that we had seen the view and removed it. However, the tree walker would then get to the render node representing the D view. Because the flag was now set to true, it would erroneously assume D was a child of C and leave it in A’s `childViews`. In this commit, we change the flag to a property that tracks the nearest view to the render node being cleaned up. As we traverse the render node tree, if we find a node with a view, we remove that view from it’s parent view’s `childViews` array if and only if its parent view is the same as the render node’s nearest view. This is a more correct version of the heuristic for determining when to remove destroyed views from their parents’ than our previous attempt.
- Loading branch information
Showing
8 changed files
with
59 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,5 @@ | ||
export default function didCleanupTree(env) { | ||
var view; | ||
if (view = env.view) { | ||
view.ownerView.isDestroyingSubtree = false; | ||
} | ||
// Once we have finsihed cleaning up the render node and sub-nodes, reset | ||
// state tracking which view those render nodes belonged to. | ||
env.view.ownerView._destroyingSubtreeForView = null; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
export default function willCleanupTree(env) { | ||
let view = env.view; | ||
|
||
// When we go to clean up the render node and all of its children, we may | ||
// encounter views/components associated with those nodes along the way. In | ||
// those cases, we need to make sure we need to sever the link between the | ||
// existing view hierarchy and those views. | ||
// | ||
// However, we do *not* need to remove the child views of child views, since | ||
// severing the connection to their parent effectively severs them from the | ||
// view graph. | ||
// | ||
// For example, imagine the following view graph: | ||
// | ||
// A | ||
// / \ | ||
// B C | ||
// / \ | ||
// D E | ||
// | ||
// If we are cleaning up the node for view C, we need to remove that view | ||
// from A's child views. However, we do not need to remove D and E from C's | ||
// child views, since removing C transitively removes D and E as well. | ||
// | ||
// To accomplish this, we track the nearest view to this render node on the | ||
// owner view, the root-most view in the graph (A in the example above). If | ||
// we detect a view that is a direct child of that view, we remove it from | ||
// the `childViews` array. Other parent/child view relationships are | ||
// untouched. This view is then cleared once cleanup is complete in | ||
// `didCleanupTree`. | ||
view.ownerView._destroyingSubtreeForView = view; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters