refactor(ivy): move child from LNode to TNode (#24113)

PR Close #24113
This commit is contained in:
Kara Erickson 2018-05-24 13:13:51 -07:00 committed by Matias Niemelä
parent 68bf8c36c6
commit 609e6b9787
5 changed files with 60 additions and 29 deletions

View File

@ -17,7 +17,7 @@ import {CurrentMatchesList, LView, LViewFlags, LifecycleStage, RootContext, TDat
import {LContainerNode, LElementNode, LNode, TNodeType, TNodeFlags, LProjectionNode, LTextNode, LViewNode, TNode, TContainerNode, InitialInputData, InitialInputs, PropertyAliases, PropertyAliasValue,} from './interfaces/node';
import {assertNodeType} from './node_assert';
import {appendChild, insertView, appendProjectedNode, removeView, canInsertNativeNode, createTextNode, getNextLNode} from './node_manipulation';
import {appendChild, insertView, appendProjectedNode, removeView, canInsertNativeNode, createTextNode, getNextLNode, getChildLNode} from './node_manipulation';
import {isNodeMatchingSelectorList, matchingSelectorIndex} from './node_selector_matcher';
import {ComponentDef, ComponentTemplate, DirectiveDef, DirectiveDefList, DirectiveDefListOrFactory, PipeDefList, PipeDefListOrFactory, RenderFlags} from './interfaces/definition';
import {RElement, RText, Renderer3, RendererFactory3, ProceduralRenderer3, RendererStyleFlags3, isProceduralRenderer} from './interfaces/renderer';
@ -344,7 +344,6 @@ export function createLNodeObject(
native: native as any,
view: currentView,
parent: parent as any,
child: null,
nodeInjector: parent ? parent.nodeInjector : null,
data: state,
queries: queries,
@ -414,15 +413,10 @@ export function createLNode(
// Now link ourselves into the tree.
if (isParent) {
currentQueries = null;
if (previousOrParentNode.view === currentView ||
if (previousOrParentNode.tNode.child == null && previousOrParentNode.view === currentView ||
previousOrParentNode.tNode.type === TNodeType.View) {
// We are in the same view, which means we are adding content node to the parent View.
ngDevMode && assertNull(
previousOrParentNode.child,
`previousOrParentNode's child should not have been set.`);
previousOrParentNode.child = node;
} else {
// We are adding component view, so we don't link parent node child to this node.
previousOrParentNode.tNode.child = node.tNode;
}
}
}
@ -1063,6 +1057,7 @@ export function createTNode(
outputs: undefined,
tViews: tViews,
next: null,
child: null,
dynamicContainerNode: null
};
}
@ -1699,7 +1694,7 @@ export function embeddedViewEnd(): void {
function setRenderParentInProjectedNodes(
renderParent: LElementNode | null, viewNode: LViewNode): void {
if (renderParent != null) {
let node: LNode|null = viewNode.child;
let node: LNode|null = getChildLNode(viewNode);
while (node) {
if (node.tNode.type === TNodeType.Projection) {
let nodeToProject: LNode|null = (node as LProjectionNode).data.head;
@ -1776,7 +1771,7 @@ export function projectionDef(
}
const componentNode: LElementNode = findComponentHost(currentView);
let componentChild: LNode|null = componentNode.child;
let componentChild: LNode|null = getChildLNode(componentNode);
while (componentChild !== null) {
// execute selector matching logic if and only if:

View File

@ -71,11 +71,6 @@ export interface LNode {
*/
readonly parent: LNode|null;
/**
* First child of the current node.
*/
child: LNode|null;
/**
* If regular LElementNode, then `data` will be null.
* If LElementNode with component, then `data` contains LView.
@ -130,8 +125,6 @@ export interface LElementNode extends LNode {
/** The DOM element associated with this node. */
readonly native: RElement;
child: LContainerNode|LElementNode|LTextNode|LProjectionNode|null;
/** If Component then data has LView (light DOM) */
readonly data: LView|null;
@ -143,7 +136,6 @@ export interface LElementNode extends LNode {
export interface LTextNode extends LNode {
/** The text node associated with this node. */
native: RText;
child: null;
/** LTextNodes can be inside LElementNodes or inside LViewNodes. */
readonly parent: LElementNode|LViewNode;
@ -154,7 +146,6 @@ export interface LTextNode extends LNode {
/** Abstract node which contains root nodes of a view. */
export interface LViewNode extends LNode {
readonly native: null;
child: LContainerNode|LElementNode|LTextNode|LProjectionNode|null;
/** LViewNodes can only be added to LContainerNodes. */
readonly parent: LContainerNode|null;
@ -173,7 +164,6 @@ export interface LContainerNode extends LNode {
*/
native: RElement|RText|null|undefined;
readonly data: LContainer;
child: null;
/** Containers can be added to elements or views. */
readonly parent: LElementNode|LViewNode|null;
@ -182,7 +172,6 @@ export interface LContainerNode extends LNode {
export interface LProjectionNode extends LNode {
readonly native: null;
child: null;
readonly data: LProjection;
@ -310,6 +299,14 @@ export interface TNode {
*/
next: TNode|null;
/**
* First child of the current node.
*
* For component nodes, the child will always be a ContentChild (in same view).
* For embedded view nodes, the child will be in their child view.
*/
child: TNode|null;
/**
* A pointer to a TContainerNode created by directives requesting ViewContainerRef
*/
@ -317,10 +314,34 @@ export interface TNode {
}
/** Static data for an LElementNode */
export interface TElementNode extends TNode { tViews: null; }
export interface TElementNode extends TNode {
child: TContainerNode|TElementNode|TProjectionNode|null;
tViews: null;
}
/** Static data for an LTextNode */
export interface TTextNode extends TNode {
child: null;
tViews: null;
}
/** Static data for an LContainerNode */
export interface TContainerNode extends TNode { tViews: TView|TView[]|null; }
export interface TContainerNode extends TNode {
child: null;
tViews: TView|TView[]|null;
}
/** Static data for an LViewNode */
export interface TViewNode extends TNode {
child: TContainerNode|TElementNode|TProjectionNode|null;
tViews: null;
}
/** Static data for an LProjectionNode */
export interface TProjectionNode extends TNode {
child: null;
tViews: null;
}
/**
* This mapping is necessary so we can set input properties and output listeners

View File

@ -75,6 +75,15 @@ export function getNextLNode(node: LNode): LNode|null {
return node.tNode.next ? node.view.data[node.tNode.next !.index as number] : null;
}
/** Retrieves the first child of a given node */
export function getChildLNode(node: LNode): LNode|null {
if (node.tNode.child) {
const view = node.tNode.type === TNodeType.View ? node.data as LView : node.view;
return view.data[node.tNode.child.index as number];
}
return null;
}
/**
* Get the next node in the LNode tree, taking into account the place where a node is
* projected (in the shadow DOM) rather than where it comes from (in the light DOM).
@ -140,13 +149,14 @@ function findFirstRNode(rootNode: LNode): RElement|RText|null {
const childContainerData: LContainer = lContainerNode.dynamicLContainerNode ?
lContainerNode.dynamicLContainerNode.data :
lContainerNode.data;
nextNode = childContainerData.views.length ? childContainerData.views[0].child : null;
nextNode =
childContainerData.views.length ? getChildLNode(childContainerData.views[0]) : null;
} else if (node.tNode.type === TNodeType.Projection) {
// For Projection look at the first projected node
nextNode = (node as LProjectionNode).data.head;
} else {
// Otherwise look at the first child
nextNode = (node as LViewNode).child;
nextNode = getChildLNode(node as LViewNode);
}
node = nextNode === null ? getNextOrParentSiblingNode(node, rootNode) : nextNode;
@ -183,7 +193,7 @@ export function addRemoveViewFromContainer(
ngDevMode && assertNodeType(rootNode, TNodeType.View);
const parentNode = container.data.renderParent;
const parent = parentNode ? parentNode.native : null;
let node: LNode|null = rootNode.child;
let node: LNode|null = getChildLNode(rootNode);
if (parent) {
while (node) {
let nextNode: LNode|null = null;
@ -203,11 +213,12 @@ export function addRemoveViewFromContainer(
// propagating down into child views / containers and not child elements
const childContainerData: LContainer = (node as LContainerNode).data;
childContainerData.renderParent = parentNode;
nextNode = childContainerData.views.length ? childContainerData.views[0].child : null;
nextNode =
childContainerData.views.length ? getChildLNode(childContainerData.views[0]) : null;
} else if (node.tNode.type === TNodeType.Projection) {
nextNode = (node as LProjectionNode).data.head;
} else {
nextNode = (node as LViewNode).child;
nextNode = getChildLNode(node as LViewNode);
}
if (nextNode === null) {
node = getNextOrParentSiblingNode(node, rootNode);

View File

@ -383,6 +383,9 @@
{
"name": "generatePropertyAliases"
},
{
"name": "getChildLNode"
},
{
"name": "getCurrentSanitizer"
},

View File

@ -22,6 +22,7 @@ function testLStaticData(tagName: string, attrs: string[] | null): TNode {
outputs: undefined,
tViews: null,
next: null,
child: null,
dynamicContainerNode: null
};
}