diff --git a/packages/core/src/render3/i18n.ts b/packages/core/src/render3/i18n.ts index 67c1e7d1ed..350b1a4f28 100644 --- a/packages/core/src/render3/i18n.ts +++ b/packages/core/src/render3/i18n.ts @@ -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; diff --git a/packages/core/src/render3/instructions.ts b/packages/core/src/render3/instructions.ts index a1013eff9b..208e91d740 100644 --- a/packages/core/src/render3/instructions.ts +++ b/packages/core/src/render3/instructions.ts @@ -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,11 +1906,7 @@ export function projectionDef( distributedNodes[0].push(componentChild); } - if (isProjectingI18nNodes) { - componentChild = componentChild.pNextOrParent; - } else { - componentChild = getNextLNode(componentChild); - } + componentChild = getNextLNode(componentChild); } ngDevMode && assertDataNext(index + HEADER_OFFSET); diff --git a/packages/core/src/render3/interfaces/node.ts b/packages/core/src/render3/interfaces/node.ts index f75ca24ce1..9194bb547b 100644 --- a/packages/core/src/render3/interfaces/node.ts +++ b/packages/core/src/render3/interfaces/node.ts @@ -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. diff --git a/packages/core/src/render3/node_manipulation.ts b/packages/core/src/render3/node_manipulation.ts index 4806de5499..d577a15c9b 100644 --- a/packages/core/src/render3/node_manipulation.ts +++ b/packages/core/src/render3/node_manipulation.ts @@ -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]; diff --git a/packages/core/test/render3/i18n_spec.ts b/packages/core/test/render3/i18n_spec.ts index b83f5080f3..98cbf07b3c 100644 --- a/packages/core/test/render3/i18n_spec.ts +++ b/packages/core/test/render3/i18n_spec.ts @@ -518,7 +518,7 @@ describe('Runtime i18n', () => { // Translated to: //