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 {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 {RENDER_PARENT} from './interfaces/container';
import {LContainerNode, LElementNode, LNode, TNodeType} from './interfaces/node'; 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 {appendChild, createTextNode, getParentLNode, removeChild} from './node_manipulation';
import {stringify} from './util'; import {stringify} from './util';
@ -240,10 +240,16 @@ function appendI18nNode(node: LNode, parentNode: LNode, previousNode: LNode) {
appendChild(parentNode, node.native || null, viewData); appendChild(parentNode, node.native || null, viewData);
if (previousNode === parentNode && parentNode.pChild === null) { // On first pass, re-organize node tree to put this node in the correct position.
parentNode.pChild = node; if (node.view[TVIEW].firstTemplatePass) {
} else { node.tNode.next = null;
previousNode.pNextOrParent = node; 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 // 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(); const renderer = getRenderer();
let localParentNode: LNode = getParentLNode(load(startIndex)) || getPreviousOrParentNode(); let localParentNode: LNode = getParentLNode(load(startIndex)) || getPreviousOrParentNode();
let localPreviousNode: LNode = localParentNode; 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++) { for (let i = 0; i < instructions.length; i++) {
const instruction = instructions[i] as number; const instruction = instructions[i] as number;
@ -298,10 +305,12 @@ export function i18nApply(startIndex: number, instructions: I18nInstruction[]):
const value = instructions[++i]; const value = instructions[++i];
const textRNode = createTextNode(value, renderer); const textRNode = createTextNode(value, renderer);
// If we were to only create a `RNode` then projections won't move the text. // 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 // Create text node at the current end of viewData. Must subtract header offset because
// `LElementNode` with the index -1 so that it isn't saved in `LViewData` // createLNode takes a raw index (not adjusted by header offset).
const textLNode = createLNode(-1, TNodeType.Element, textRNode, null, null); const textLNode =
createLNode(viewData.length - HEADER_OFFSET, TNodeType.Element, textRNode, null, null);
localPreviousNode = appendI18nNode(textLNode, localParentNode, localPreviousNode); localPreviousNode = appendI18nNode(textLNode, localParentNode, localPreviousNode);
resetApplicationState();
break; break;
case I18nInstructions.CloseNode: case I18nInstructions.CloseNode:
localPreviousNode = localParentNode; localPreviousNode = localParentNode;

View File

@ -335,8 +335,7 @@ export function createLNodeObject(
queries: queries, queries: queries,
tNode: null !, tNode: null !,
pNextOrParent: null, pNextOrParent: null,
dynamicLContainerNode: null, dynamicLContainerNode: null
pChild: null,
}; };
} }
@ -440,7 +439,7 @@ export function createLNode(
/** /**
* Resets the application state. * Resets the application state.
*/ */
function resetApplicationState() { export function resetApplicationState() {
isParent = false; isParent = false;
previousOrParentNode = null !; previousOrParentNode = null !;
} }
@ -1894,16 +1893,7 @@ export function projectionDef(
} }
const componentNode: LElementNode = findComponentHost(viewData); const componentNode: LElementNode = findComponentHost(viewData);
let isProjectingI18nNodes = false; let componentChild = getChildLNode(componentNode);
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);
}
while (componentChild !== null) { while (componentChild !== null) {
// execute selector matching logic if and only if: // execute selector matching logic if and only if:
@ -1916,11 +1906,7 @@ export function projectionDef(
distributedNodes[0].push(componentChild); distributedNodes[0].push(componentChild);
} }
if (isProjectingI18nNodes) { componentChild = getNextLNode(componentChild);
componentChild = componentChild.pNextOrParent;
} else {
componentChild = getNextLNode(componentChild);
}
} }
ngDevMode && assertDataNext(index + HEADER_OFFSET); ngDevMode && assertDataNext(index + HEADER_OFFSET);

View File

@ -100,13 +100,6 @@ export interface LNode {
*/ */
pNextOrParent: LNode|null; 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 * Pointer to the corresponding TNode object, which stores static
* data about this node. * 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 */ /** Retrieves the first child of a given node */
export function getChildLNode(node: LNode): LNode|null { export function getChildLNode(node: LNode): LNode|null {
if (node.pChild) {
return node.pChild;
}
if (node.tNode.child) { if (node.tNode.child) {
const viewData = node.tNode.type === TNodeType.View ? node.data as LViewData : node.view; const viewData = node.tNode.type === TNodeType.View ? node.data as LViewData : node.view;
return viewData[node.tNode.child.index]; return viewData[node.tNode.child.index];

View File

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