diff --git a/packages/core/src/render3/instructions/element.ts b/packages/core/src/render3/instructions/element.ts index 3b6eb3e4116ea..26a2294dc6c43 100644 --- a/packages/core/src/render3/instructions/element.ts +++ b/packages/core/src/render3/instructions/element.ts @@ -84,7 +84,7 @@ export function ɵɵelementStart( ngDevMode && ngDevMode.firstTemplatePass++; resolveDirectives(tView, lView, tNode, localRefs || null); - const inputData = initializeTNodeInputs(tNode); + const inputData = initializeTNodeInputs(tView, tNode); if (inputData && inputData.hasOwnProperty('class')) { tNode.flags |= TNodeFlags.hasClassInput; } diff --git a/packages/core/src/render3/instructions/listener.ts b/packages/core/src/render3/instructions/listener.ts index 6b58d46be3a98..33b4a3b6e836f 100644 --- a/packages/core/src/render3/instructions/listener.ts +++ b/packages/core/src/render3/instructions/listener.ts @@ -179,7 +179,7 @@ function listenerInternal( if (tNode.outputs === undefined) { // if we create TNode here, inputs must be undefined so we know they still need to be // checked - tNode.outputs = generatePropertyAliases(tNode, BindingDirection.Output); + tNode.outputs = generatePropertyAliases(tView, tNode, BindingDirection.Output); } const outputs = tNode.outputs; diff --git a/packages/core/src/render3/instructions/shared.ts b/packages/core/src/render3/instructions/shared.ts index dc8587c41d5a6..7b72d90168f2d 100644 --- a/packages/core/src/render3/instructions/shared.ts +++ b/packages/core/src/render3/instructions/shared.ts @@ -212,7 +212,7 @@ export function getOrCreateTNode( // Keep this function short, so that the VM will inline it. const adjustedIndex = index + HEADER_OFFSET; const tNode = tView.data[adjustedIndex] as TNode || - createTNodeAtIndex(tView, tHostNode, adjustedIndex, type, name, attrs, index); + createTNodeAtIndex(tView, tHostNode, adjustedIndex, type, name, attrs); setPreviousOrParentTNode(tNode, true); return tNode as TElementNode & TViewNode & TContainerNode & TElementContainerNode & TProjectionNode & TIcuContainerNode; @@ -220,7 +220,7 @@ export function getOrCreateTNode( function createTNodeAtIndex( tView: TView, tHostNode: TNode | null, adjustedIndex: number, type: TNodeType, - name: string | null, attrs: TAttributes | null, index: number) { + name: string | null, attrs: TAttributes | null) { const previousOrParentTNode = getPreviousOrParentTNode(); const isParent = getIsParent(); const parent = @@ -231,9 +231,10 @@ function createTNodeAtIndex( const tParentNode = parentInSameView ? parent as TElementNode | TContainerNode : null; const tNode = tView.data[adjustedIndex] = createTNode(tView, tParentNode, type, adjustedIndex, name, attrs); - // The first node is not always the one at index 0, in case of i18n, index 0 can be the - // instruction `i18nStart` and the first node has the index 1 or more - if (index === 0 || !tView.firstChild) { + // Assign a pointer to the first child node of a given view. The first node is not always the one + // at index 0, in case of i18n, index 0 can be the instruction `i18nStart` and the first node has + // the index 1 or more, so we can't just check node index. + if (tView.firstChild === null) { tView.firstChild = tNode; } if (previousOrParentTNode) { @@ -812,9 +813,8 @@ export function createTNode( * @param direction whether to consider inputs or outputs * @returns PropertyAliases|null aggregate of all properties if any, `null` otherwise */ -export function generatePropertyAliases(tNode: TNode, direction: BindingDirection): PropertyAliases| - null { - const tView = getLView()[TVIEW]; +export function generatePropertyAliases( + tView: TView, tNode: TNode, direction: BindingDirection): PropertyAliases|null { let propStore: PropertyAliases|null = null; const start = tNode.directiveStart; const end = tNode.directiveEnd; @@ -864,7 +864,7 @@ export function elementPropertyInternal( const tNode = getTNode(index, lView); let inputData: PropertyAliases|null|undefined; let dataValue: PropertyAliasValue|undefined; - if (!nativeOnly && (inputData = initializeTNodeInputs(tNode)) && + if (!nativeOnly && (inputData = initializeTNodeInputs(lView[TVIEW], tNode)) && (dataValue = inputData[propName])) { setInputsForProperty(lView, dataValue, value); if (isComponent(tNode)) markDirtyIfOnPush(lView, index + HEADER_OFFSET); @@ -1785,12 +1785,12 @@ export function storeBindingMetadata(lView: LView, prefix = '', suffix = ''): st export const CLEAN_PROMISE = _CLEAN_PROMISE; -export function initializeTNodeInputs(tNode: TNode): PropertyAliases|null { +export function initializeTNodeInputs(tView: TView, tNode: TNode): PropertyAliases|null { // If tNode.inputs is undefined, a listener has created outputs, but inputs haven't // yet been checked. if (tNode.inputs === undefined) { // mark inputs as checked - tNode.inputs = generatePropertyAliases(tNode, BindingDirection.Input); + tNode.inputs = generatePropertyAliases(tView, tNode, BindingDirection.Input); } return tNode.inputs; }