refactor(ivy): simplify logic around canInsertNativeNode (#28011)

Previously presence and type of a parent tNode was split among
canInsertNativeNode, canInsertNativeChildOfView and canInsertNativeChildOfElement.
This commit centralises the logic in canInsertNativeNode thus simplifying
the overall logic and making canInsertNativeChildOfElement trivial.

PR Close #28011
This commit is contained in:
Pawel Kozlowski 2019-01-09 11:59:49 +01:00 committed by Andrew Kushnir
parent 9b2b9b3bef
commit 1f904bffbc
1 changed files with 27 additions and 23 deletions

View File

@ -508,21 +508,11 @@ export function getRenderParent(tNode: TNode, currentView: LView): RElement|null
return null; return null;
} }
function canInsertNativeChildOfElement(tNode: TNode): boolean { function canInsertNativeChildOfElement(tNode: TElementNode): boolean {
// If the parent is null, then we are inserting across views. This happens when we // Component's content nodes are not inserted immediately
// insert a root element of the component view into the component host element and it
// should always be eager.
if (tNode.parent == null ||
// We should also eagerly insert if the parent is a regular, non-component element
// since we know that this relationship will never be broken.
tNode.parent.type === TNodeType.Element && !(tNode.parent.flags & TNodeFlags.isComponent)) {
return true;
}
// Parent is a Component. Component's content nodes are not inserted immediately
// because they will be projected, and so doing insert at this point would be wasteful. // because they will be projected, and so doing insert at this point would be wasteful.
// Since the projection would than move it to its final destination. // Since the projection would than move it to its final destination.
return false; return !(tNode.flags & TNodeFlags.isComponent);
} }
/** /**
@ -569,19 +559,33 @@ function canInsertNativeChildOfView(viewTNode: TViewNode, view: LView): boolean
* @return boolean Whether the node should be inserted now (or delayed until later). * @return boolean Whether the node should be inserted now (or delayed until later).
*/ */
export function canInsertNativeNode(tNode: TNode, currentView: LView): boolean { export function canInsertNativeNode(tNode: TNode, currentView: LView): boolean {
let currentNode = tNode; // Nodes of the top-most view can be inserted eagerly
let parent: TNode|null; if (isRootView(currentView)) {
return true;
}
currentNode = getHighestElementOrICUContainer(currentNode); const parent = getHighestElementOrICUContainer(tNode).parent;
parent = currentNode.parent;
if (parent === null) parent = currentView[HOST_NODE]; // If the parent is null, then we are inserting across views: either into an embedded view or a
// component view.
if (parent && parent.type === TNodeType.View) { if (parent == null) {
return canInsertNativeChildOfView(parent as TViewNode, currentView); const hostTNode = currentView[HOST_NODE] !;
if (hostTNode.type === TNodeType.View) {
// We are inserting a root element of an embedded view - this should only be possible if the
// embedded view in question is already inserted into a container and the container itself is
// inserted into the DOM.
return canInsertNativeChildOfView(hostTNode as TViewNode, currentView);
} else {
// We are inserting a root element of the component view into the component host element and
// it should always be eager.
return true;
}
} else { } else {
// Parent is a regular element or a component ngDevMode && assertNodeType(parent, TNodeType.Element);
return canInsertNativeChildOfElement(currentNode); // We've got a parent which is an element in the current view. We just need to verify if the
// parent element is not a component (this would mean that the tNode represents a root content
// node of a component and its insertion should be delayed due to content projection).
return canInsertNativeChildOfElement(parent as TElementNode);
} }
} }