refactor(ivy): misc refactoring (#22001)

PR Close #22001
This commit is contained in:
Victor Berchet 2018-02-02 14:59:31 -08:00 committed by Alex Rickabaugh
parent 5a624fa1be
commit 5df626bbe1
3 changed files with 39 additions and 34 deletions

View File

@ -9,8 +9,7 @@
import {LContainerNode, LElementNode, LTextNode} from './node'; import {LContainerNode, LElementNode, LTextNode} from './node';
/** /**
* An LProjection is a pointer to the first and the last projected nodes. * Linked list of projected nodes (using the pNextOrParent property).
* It is a linked list (using the pNextOrParent property).
*/ */
export interface LProjection { export interface LProjection {
head: LElementNode|LTextNode|LContainerNode|null; head: LElementNode|LTextNode|LContainerNode|null;

View File

@ -18,7 +18,7 @@ import {Renderer3} from './renderer';
* they are invoked from the template. Each embedded view and component view has its * they are invoked from the template. Each embedded view and component view has its
* own `LView`. When processing a particular view, we set the `currentView` to that * own `LView`. When processing a particular view, we set the `currentView` to that
* `LView`. When that view is done processing, the `currentView` is set back to * `LView`. When that view is done processing, the `currentView` is set back to
* whatever the original `currentView` was before(the parent `LView`). * whatever the original `currentView` was before (the parent `LView`).
* *
* Keeping separate state for each view facilities view insertion / deletion, so we * Keeping separate state for each view facilities view insertion / deletion, so we
* don't have to edit the data array based on which views are present. * don't have to edit the data array based on which views are present.

View File

@ -18,25 +18,25 @@ import {assertNodeType} from './node_assert';
const unusedValueToPlacateAjd = unused1 + unused2 + unused3 + unused4 + unused5; const unusedValueToPlacateAjd = unused1 + unused2 + unused3 + unused4 + unused5;
/** /**
* Returns the first DOM node following the given logical node in the same parent DOM element. * Returns the first RNode following the given LNode in the same parent DOM element.
* *
* This is needed in order to insert the given node with insertBefore. * This is needed in order to insert the given node with insertBefore.
* *
* @param node The node whose following DOM node must be found. * @param node The node whose following DOM node must be found.
* @param stopNode A parent node at which the lookup in the tree should be stopped, or null if the * @param stopNode A parent node at which the lookup in the tree should be stopped, or null if the
* lookup should not be stopped until the result is found. * lookup should not be stopped until the result is found.
* @returns Node before which the provided node should be inserted or null if the lookup was stopped * @returns RNode before which the provided node should be inserted or null if the lookup was
* stopped
* or if there is no native node after the given logical node in the same native parent. * or if there is no native node after the given logical node in the same native parent.
*/ */
function findBeforeNode(node: LNode | null, stopNode: LNode | null): RElement|RText|null { function findNextRNodeSibling(node: LNode | null, stopNode: LNode | null): RElement|RText|null {
let currentNode = node; let currentNode = node;
while (currentNode && currentNode !== stopNode) { while (currentNode && currentNode !== stopNode) {
const currentNodeType = currentNode.flags && LNodeFlags.TYPE_MASK;
let pNextOrParent = currentNode.pNextOrParent; let pNextOrParent = currentNode.pNextOrParent;
if (pNextOrParent) { if (pNextOrParent) {
let pNextOrParentType = pNextOrParent.flags & LNodeFlags.TYPE_MASK; let pNextOrParentType = pNextOrParent.flags & LNodeFlags.TYPE_MASK;
while (pNextOrParentType !== LNodeFlags.Projection) { while (pNextOrParentType !== LNodeFlags.Projection) {
const nativeNode = findFirstNativeNode(pNextOrParent); const nativeNode = findFirstRNode(pNextOrParent);
if (nativeNode) { if (nativeNode) {
return nativeNode; return nativeNode;
} }
@ -46,7 +46,7 @@ function findBeforeNode(node: LNode | null, stopNode: LNode | null): RElement|RT
} else { } else {
let currentSibling = currentNode.next; let currentSibling = currentNode.next;
while (currentSibling) { while (currentSibling) {
const nativeNode = findFirstNativeNode(currentSibling); const nativeNode = findFirstRNode(currentSibling);
if (nativeNode) { if (nativeNode) {
return nativeNode; return nativeNode;
} }
@ -68,72 +68,78 @@ function findBeforeNode(node: LNode | null, stopNode: LNode | null): RElement|RT
/** /**
* 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).
* If the node is not projected, the return value is simply node.next. *
* If the node is projected, the return value is node.pNextOrParent if node.pNextOrParent is
* not a projection node (which marks the end of the linked list).
* Otherwise the return value is null.
* @param node The node whose next node in the LNode tree must be found. * @param node The node whose next node in the LNode tree must be found.
* @return The next sibling in the LNode tree. * @return LNode|null The next sibling in the LNode tree.
*/ */
function getNextNode(node: LNode): LNode|null { function getNextLNodeWithProjection(node: LNode): LNode|null {
const pNextOrParent = node.pNextOrParent; const pNextOrParent = node.pNextOrParent;
if (pNextOrParent) { if (pNextOrParent) {
return (pNextOrParent.flags & LNodeFlags.TYPE_MASK) === LNodeFlags.Projection ? null : // The node is projected
pNextOrParent; const isLastProjectedNode =
} else { (pNextOrParent.flags & LNodeFlags.TYPE_MASK) === LNodeFlags.Projection;
return node.next; // returns pNextOrParent if we are not at the end of the list, null otherwise
return isLastProjectedNode ? null : pNextOrParent;
} }
// returns node.next because the the node is not projected
return node.next;
} }
/** /**
* Find the next node in the LNode tree, taking into account the place where a node is * Find 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).
*
* If there is no sibling node, this function goes to the next sibling of the parent node... * If there is no sibling node, this function goes to the next sibling of the parent node...
* until it reaches rootNode (at which point null is returned). * until it reaches rootNode (at which point null is returned).
* *
* @param initialNode The node whose following node in the LNode tree must be found. * @param initialNode The node whose following node in the LNode tree must be found.
* @param rootNode The root node at which the lookup should stop. * @param rootNode The root node at which the lookup should stop.
* @return The following node in the LNode tree. * @return LNode|null The following node in the LNode tree.
*/ */
function getNextOrParentSiblingNode(initialNode: LNode, rootNode: LNode): LNode|null { function getNextOrParentSiblingNode(initialNode: LNode, rootNode: LNode): LNode|null {
let node: LNode|null = initialNode; let node: LNode|null = initialNode;
let nextNode = getNextNode(node); let nextNode = getNextLNodeWithProjection(node);
while (node && !nextNode) { while (node && !nextNode) {
// if node.pNextOrParent is not null here, it is not the next node // if node.pNextOrParent is not null here, it is not the next node
// (because, at this point, nextNode is null, so it is the parent) // (because, at this point, nextNode is null, so it is the parent)
node = node.pNextOrParent || node.parent; node = node.pNextOrParent || node.parent;
if (node === rootNode) node = null; if (node === rootNode) {
nextNode = node && getNextNode(node); return null;
}
nextNode = node && getNextLNodeWithProjection(node);
} }
return nextNode; return nextNode;
} }
/** /**
* Returns the first DOM node inside the given logical node. * Returns the first RNode inside the given LNode.
* *
* @param node The node whose first DOM node must be found * @param node The node whose first DOM node must be found
* @returns The first native node of the given logical node or null if there is none. * @returns RNode The first RNode of the given LNode or null if there is none.
*/ */
function findFirstNativeNode(rootNode: LNode): RElement|RText|null { function findFirstRNode(rootNode: LNode): RElement|RText|null {
let node: LNode|null = rootNode; let node: LNode|null = rootNode;
while (node) { while (node) {
const type = node.flags & LNodeFlags.TYPE_MASK; const type = node.flags & LNodeFlags.TYPE_MASK;
let nextNode: LNode|null = null; let nextNode: LNode|null = null;
if (type === LNodeFlags.Element) { if (type === LNodeFlags.Element) {
// A LElementNode has a matching RNode in LElementNode.native
return (node as LElementNode).native; return (node as LElementNode).native;
} else if (type === LNodeFlags.Container) { } else if (type === LNodeFlags.Container) {
// For container look at the first node of the view next
const childContainerData: LContainer = (node as LContainerNode).data; const childContainerData: LContainer = (node as LContainerNode).data;
nextNode = childContainerData.views.length ? childContainerData.views[0].child : null; nextNode = childContainerData.views.length ? childContainerData.views[0].child : null;
} else if (type === LNodeFlags.Projection) { } else if (type === LNodeFlags.Projection) {
// 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
nextNode = (node as LViewNode).child; nextNode = (node as LViewNode).child;
} }
if (nextNode === null) {
node = getNextOrParentSiblingNode(node, rootNode); node = nextNode === null ? getNextOrParentSiblingNode(node, rootNode) : nextNode;
} else {
node = nextNode;
}
} }
return null; return null;
} }
@ -279,11 +285,11 @@ export function insertView(
// and we should wait until that parent processes its nodes (otherwise, we will insert this view's // and we should wait until that parent processes its nodes (otherwise, we will insert this view's
// nodes twice - once now and once when its parent inserts its views). // nodes twice - once now and once when its parent inserts its views).
if (container.data.renderParent !== null) { if (container.data.renderParent !== null) {
let beforeNode = findBeforeNode(newView, container); let beforeNode = findNextRNodeSibling(newView, container);
if (!beforeNode) { if (!beforeNode) {
let containerNextNativeNode = container.native; let containerNextNativeNode = container.native;
if (containerNextNativeNode === undefined) { if (containerNextNativeNode === undefined) {
containerNextNativeNode = container.native = findBeforeNode(container, null); containerNextNativeNode = container.native = findNextRNodeSibling(container, null);
} }
beforeNode = containerNextNativeNode; beforeNode = containerNextNativeNode;
} }
@ -470,7 +476,7 @@ export function insertChild(node: LNode, currentView: LView): void {
if (canInsertNativeNode(parent, currentView)) { if (canInsertNativeNode(parent, currentView)) {
// We only add element if not in View or not projected. // We only add element if not in View or not projected.
let nativeSibling: RNode|null = findBeforeNode(node, null); let nativeSibling: RNode|null = findNextRNodeSibling(node, null);
const renderer = currentView.renderer; const renderer = currentView.renderer;
(renderer as ProceduralRenderer3).listen ? (renderer as ProceduralRenderer3).listen ?
(renderer as ProceduralRenderer3) (renderer as ProceduralRenderer3)