refactor(ivy): remove pChild from LNode (#24705)

PR Close #24705
This commit is contained in:
Kara Erickson 2018-06-28 16:40:16 -07:00 committed by Misko Hevery
parent ff84c5c4da
commit d243baf48a
5 changed files with 23 additions and 38 deletions

View File

@ -7,10 +7,10 @@
*/
import {assertEqual, assertLessThan} from './assert';
import {NO_CHANGE, bindingUpdated, createLNode, getPreviousOrParentNode, getRenderer, getViewData, load} from './instructions';
import {NO_CHANGE, bindingUpdated, createLNode, getPreviousOrParentNode, getRenderer, getViewData, load, resetApplicationState} from './instructions';
import {RENDER_PARENT} from './interfaces/container';
import {LContainerNode, LElementNode, LNode, TNodeType} from './interfaces/node';
import {BINDING_INDEX} from './interfaces/view';
import {BINDING_INDEX, HEADER_OFFSET, TVIEW} from './interfaces/view';
import {appendChild, createTextNode, getParentLNode, removeChild} from './node_manipulation';
import {stringify} from './util';
@ -240,10 +240,16 @@ function appendI18nNode(node: LNode, parentNode: LNode, previousNode: LNode) {
appendChild(parentNode, node.native || null, viewData);
if (previousNode === parentNode && parentNode.pChild === null) {
parentNode.pChild = node;
} else {
previousNode.pNextOrParent = node;
// On first pass, re-organize node tree to put this node in the correct position.
if (node.view[TVIEW].firstTemplatePass) {
node.tNode.next = null;
if (previousNode === parentNode && node.tNode !== parentNode.tNode.child) {
node.tNode.next = parentNode.tNode.child;
parentNode.tNode.child = node.tNode;
} else if (previousNode !== parentNode && node.tNode !== previousNode.tNode.next) {
node.tNode.next = previousNode.tNode.next;
previousNode.tNode.next = node.tNode;
}
}
// Template containers also have a comment node for the `ViewContainerRef` that should be moved
@ -278,6 +284,7 @@ export function i18nApply(startIndex: number, instructions: I18nInstruction[]):
const renderer = getRenderer();
let localParentNode: LNode = getParentLNode(load(startIndex)) || getPreviousOrParentNode();
let localPreviousNode: LNode = localParentNode;
resetApplicationState(); // We don't want to add to the tree with the wrong previous node
for (let i = 0; i < instructions.length; i++) {
const instruction = instructions[i] as number;
@ -298,10 +305,12 @@ export function i18nApply(startIndex: number, instructions: I18nInstruction[]):
const value = instructions[++i];
const textRNode = createTextNode(value, renderer);
// If we were to only create a `RNode` then projections won't move the text.
// But since this text doesn't have an index in `LViewData`, we need to create an
// `LElementNode` with the index -1 so that it isn't saved in `LViewData`
const textLNode = createLNode(-1, TNodeType.Element, textRNode, null, null);
// Create text node at the current end of viewData. Must subtract header offset because
// createLNode takes a raw index (not adjusted by header offset).
const textLNode =
createLNode(viewData.length - HEADER_OFFSET, TNodeType.Element, textRNode, null, null);
localPreviousNode = appendI18nNode(textLNode, localParentNode, localPreviousNode);
resetApplicationState();
break;
case I18nInstructions.CloseNode:
localPreviousNode = localParentNode;

View File

@ -335,8 +335,7 @@ export function createLNodeObject(
queries: queries,
tNode: null !,
pNextOrParent: null,
dynamicLContainerNode: null,
pChild: null,
dynamicLContainerNode: null
};
}
@ -440,7 +439,7 @@ export function createLNode(
/**
* Resets the application state.
*/
function resetApplicationState() {
export function resetApplicationState() {
isParent = false;
previousOrParentNode = null !;
}
@ -1894,16 +1893,7 @@ export function projectionDef(
}
const componentNode: LElementNode = findComponentHost(viewData);
let isProjectingI18nNodes = false;
let componentChild: LNode|null;
// for i18n translations we use pChild to point to the next child
// TODO(kara): Remove when removing LNodes
if (componentNode.pChild) {
isProjectingI18nNodes = true;
componentChild = componentNode.pChild;
} else {
componentChild = getChildLNode(componentNode);
}
let componentChild = getChildLNode(componentNode);
while (componentChild !== null) {
// execute selector matching logic if and only if:
@ -1916,12 +1906,8 @@ export function projectionDef(
distributedNodes[0].push(componentChild);
}
if (isProjectingI18nNodes) {
componentChild = componentChild.pNextOrParent;
} else {
componentChild = getNextLNode(componentChild);
}
}
ngDevMode && assertDataNext(index + HEADER_OFFSET);
store(index, distributedNodes);

View File

@ -100,13 +100,6 @@ export interface LNode {
*/
pNextOrParent: LNode|null;
/**
* If this node is part of an i18n block, pointer to the first child after translation
* If this node is not part of an i18n block, this field is null.
*/
// TODO(kara): Remove this when removing pNextOrParent
pChild: LNode|null;
/**
* Pointer to the corresponding TNode object, which stores static
* data about this node.

View File

@ -29,9 +29,6 @@ export function getNextLNode(node: LNode): LNode|null {
/** Retrieves the first child of a given node */
export function getChildLNode(node: LNode): LNode|null {
if (node.pChild) {
return node.pChild;
}
if (node.tNode.child) {
const viewData = node.tNode.type === TNodeType.View ? node.data as LViewData : node.view;
return viewData[node.tNode.child.index];

View File

@ -518,7 +518,7 @@ describe('Runtime i18n', () => {
// Translated to:
// <ul i18n>
// <li *ngFor="let item of items">valeur: {{item}}</li>
// <li *ngFor="let item of items">valeur: {{item}}!</li>
// </ul>
template: (rf: RenderFlags, myApp: MyApp) => {
if (rf & RenderFlags.Create) {