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

View File

@ -71,11 +71,6 @@ export interface LNode {
*/ */
readonly parent: LNode|null; readonly parent: LNode|null;
/**
* First child of the current node.
*/
child: LNode|null;
/** /**
* If regular LElementNode, then `data` will be null. * If regular LElementNode, then `data` will be null.
* If LElementNode with component, then `data` contains LView. * If LElementNode with component, then `data` contains LView.
@ -130,8 +125,6 @@ export interface LElementNode extends LNode {
/** The DOM element associated with this node. */ /** The DOM element associated with this node. */
readonly native: RElement; readonly native: RElement;
child: LContainerNode|LElementNode|LTextNode|LProjectionNode|null;
/** If Component then data has LView (light DOM) */ /** If Component then data has LView (light DOM) */
readonly data: LView|null; readonly data: LView|null;
@ -143,7 +136,6 @@ export interface LElementNode extends LNode {
export interface LTextNode extends LNode { export interface LTextNode extends LNode {
/** The text node associated with this node. */ /** The text node associated with this node. */
native: RText; native: RText;
child: null;
/** LTextNodes can be inside LElementNodes or inside LViewNodes. */ /** LTextNodes can be inside LElementNodes or inside LViewNodes. */
readonly parent: LElementNode|LViewNode; readonly parent: LElementNode|LViewNode;
@ -154,7 +146,6 @@ export interface LTextNode extends LNode {
/** Abstract node which contains root nodes of a view. */ /** Abstract node which contains root nodes of a view. */
export interface LViewNode extends LNode { export interface LViewNode extends LNode {
readonly native: null; readonly native: null;
child: LContainerNode|LElementNode|LTextNode|LProjectionNode|null;
/** LViewNodes can only be added to LContainerNodes. */ /** LViewNodes can only be added to LContainerNodes. */
readonly parent: LContainerNode|null; readonly parent: LContainerNode|null;
@ -173,7 +164,6 @@ export interface LContainerNode extends LNode {
*/ */
native: RElement|RText|null|undefined; native: RElement|RText|null|undefined;
readonly data: LContainer; readonly data: LContainer;
child: null;
/** Containers can be added to elements or views. */ /** Containers can be added to elements or views. */
readonly parent: LElementNode|LViewNode|null; readonly parent: LElementNode|LViewNode|null;
@ -182,7 +172,6 @@ export interface LContainerNode extends LNode {
export interface LProjectionNode extends LNode { export interface LProjectionNode extends LNode {
readonly native: null; readonly native: null;
child: null;
readonly data: LProjection; readonly data: LProjection;
@ -310,6 +299,14 @@ export interface TNode {
*/ */
next: TNode|null; 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 * A pointer to a TContainerNode created by directives requesting ViewContainerRef
*/ */
@ -317,10 +314,34 @@ export interface TNode {
} }
/** Static data for an LElementNode */ /** 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 */ /** 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 * 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; 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 * 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). * 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 ? const childContainerData: LContainer = lContainerNode.dynamicLContainerNode ?
lContainerNode.dynamicLContainerNode.data : lContainerNode.dynamicLContainerNode.data :
lContainerNode.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) { } else if (node.tNode.type === TNodeType.Projection) {
// For Projection look at the first projected node // For Projection look at the first projected node
nextNode = (node as LProjectionNode).data.head; nextNode = (node as LProjectionNode).data.head;
} else { } else {
// Otherwise look at the first child // Otherwise look at the first child
nextNode = (node as LViewNode).child; nextNode = getChildLNode(node as LViewNode);
} }
node = nextNode === null ? getNextOrParentSiblingNode(node, rootNode) : nextNode; node = nextNode === null ? getNextOrParentSiblingNode(node, rootNode) : nextNode;
@ -183,7 +193,7 @@ export function addRemoveViewFromContainer(
ngDevMode && assertNodeType(rootNode, TNodeType.View); ngDevMode && assertNodeType(rootNode, TNodeType.View);
const parentNode = container.data.renderParent; const parentNode = container.data.renderParent;
const parent = parentNode ? parentNode.native : null; const parent = parentNode ? parentNode.native : null;
let node: LNode|null = rootNode.child; let node: LNode|null = getChildLNode(rootNode);
if (parent) { if (parent) {
while (node) { while (node) {
let nextNode: LNode|null = null; let nextNode: LNode|null = null;
@ -203,11 +213,12 @@ export function addRemoveViewFromContainer(
// propagating down into child views / containers and not child elements // propagating down into child views / containers and not child elements
const childContainerData: LContainer = (node as LContainerNode).data; const childContainerData: LContainer = (node as LContainerNode).data;
childContainerData.renderParent = parentNode; 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) { } else if (node.tNode.type === TNodeType.Projection) {
nextNode = (node as LProjectionNode).data.head; nextNode = (node as LProjectionNode).data.head;
} else { } else {
nextNode = (node as LViewNode).child; nextNode = getChildLNode(node as LViewNode);
} }
if (nextNode === null) { if (nextNode === null) {
node = getNextOrParentSiblingNode(node, rootNode); node = getNextOrParentSiblingNode(node, rootNode);

View File

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

View File

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