diff --git a/packages/core/src/render3/instructions/shared.ts b/packages/core/src/render3/instructions/shared.ts index 2c1cbd4b8c..8c69f4e0b0 100644 --- a/packages/core/src/render3/instructions/shared.ts +++ b/packages/core/src/render3/instructions/shared.ts @@ -39,7 +39,7 @@ import {getLViewParent} from '../util/view_traversal_utils'; import {getComponentViewByIndex, getNativeByIndex, getNativeByTNode, getTNode, isCreationMode, readPatchedLView, resetPreOrderHookFlags, unwrapRNode, viewAttachedToChangeDetector} from '../util/view_utils'; import {selectIndexInternal} from './advance'; -import {LCleanup, LViewBlueprint, MatchesArray, TCleanup, TNodeConstructor, TNodeInitialData, TNodeInitialInputs, TNodeLocalNames, TViewComponents, TViewConstructor, attachLContainerDebug, attachLViewDebug, cloneToLView, cloneToTViewData} from './lview_debug'; +import {LCleanup, LViewBlueprint, MatchesArray, TCleanup, TNodeConstructor, TNodeInitialInputs, TNodeLocalNames, TViewComponents, TViewConstructor, attachLContainerDebug, attachLViewDebug, cloneToLView, cloneToTViewData} from './lview_debug'; @@ -840,11 +840,16 @@ function initializeInputAndOutputAliases(tView: TView, tNode: TNode): void { const end = tNode.directiveEnd; const defs = tView.data; + const tNodeAttrs = tNode.attrs; + const inputsFromAttrs: InitialInputData = ngDevMode ? new TNodeInitialInputs() : []; let inputsStore: PropertyAliases|null = null; let outputsStore: PropertyAliases|null = null; for (let i = start; i < end; i++) { const directiveDef = defs[i] as DirectiveDef; - inputsStore = generatePropertyAliases(directiveDef.inputs, i, inputsStore); + const directiveInputs = directiveDef.inputs; + inputsFromAttrs.push( + tNodeAttrs !== null ? generateInitialInputs(directiveInputs, tNodeAttrs) : null); + inputsStore = generatePropertyAliases(directiveInputs, i, inputsStore); outputsStore = generatePropertyAliases(directiveDef.outputs, i, outputsStore); } @@ -857,6 +862,7 @@ function initializeInputAndOutputAliases(tView: TView, tNode: TNode): void { } } + tNode.initialInputs = inputsFromAttrs; tNode.inputs = inputsStore; tNode.outputs = outputsStore; } @@ -1046,7 +1052,7 @@ export function resolveDirectives( const directives: DirectiveDef[]|null = findDirectiveMatches(tView, lView, tNode); const exportsMap: ({[key: string]: number} | null) = localRefs ? {'': -1} : null; - if (directives) { + if (directives !== null) { initNodeFlags(tNode, tView.data.length, directives.length); // When the same token is provided by several directives on the same node, some rules apply in // the viewEngine: @@ -1102,7 +1108,7 @@ function instantiateAllDirectives(tView: TView, lView: LView, tNode: TNode) { addComponentLogic(lView, tNode, def as ComponentDef); } const directive = getNodeInjectable(tView.data, lView !, i, tNode as TElementNode); - postProcessDirective(lView, tNode, directive, def, i); + postProcessDirective(lView, tNode, directive, def, i - start); } } @@ -1176,7 +1182,7 @@ function postProcessDirective( lView: LView, hostTNode: TNode, directive: T, def: DirectiveDef, directiveDefIdx: number): void { postProcessBaseDirective(lView, hostTNode, directive); - if (hostTNode.attrs !== null) { + if (hostTNode.initialInputs !== null) { setInputsFromAttrs(lView, directiveDefIdx, directive, def, hostTNode); } @@ -1362,12 +1368,8 @@ export function elementAttributeInternal( */ function setInputsFromAttrs( lView: LView, directiveIndex: number, instance: T, def: DirectiveDef, tNode: TNode): void { - let initialInputData = tNode.initialInputs as InitialInputData | undefined; - if (initialInputData === undefined || directiveIndex >= initialInputData.length) { - initialInputData = generateInitialInputs(directiveIndex, def.inputs, tNode); - } - - const initialInputs: InitialInputs|null = initialInputData[directiveIndex]; + const initialInputData = tNode.initialInputs as InitialInputData; + const initialInputs: InitialInputs|null = initialInputData ![directiveIndex]; if (initialInputs !== null) { const setInput = def.setInput; for (let i = 0; i < initialInputs.length;) { @@ -1398,20 +1400,12 @@ function setInputsFromAttrs( * * * - * @param directiveIndex Index to store the initial input data * @param inputs The list of inputs from the directive def - * @param tNode The static data on this node + * @param attrs The static attrs on this node */ -function generateInitialInputs( - directiveIndex: number, inputs: {[key: string]: string}, tNode: TNode): InitialInputData { - const initialInputData: InitialInputData = - tNode.initialInputs || (tNode.initialInputs = ngDevMode ? new TNodeInitialInputs() : []); - // Ensure that we don't create sparse arrays - for (let i = initialInputData.length; i <= directiveIndex; i++) { - initialInputData.push(null); - } - - const attrs = tNode.attrs !; +function generateInitialInputs(inputs: {[key: string]: string}, attrs: TAttributes): InitialInputs| + null { + let inputsToStore: InitialInputs|null = null; let i = 0; while (i < attrs.length) { const attrName = attrs[i]; @@ -1428,18 +1422,14 @@ function generateInitialInputs( // If we hit any other attribute markers, we're done anyway. None of those are valid inputs. if (typeof attrName === 'number') break; - const minifiedInputName = inputs[attrName as string]; - const attrValue = attrs[i + 1]; - - if (minifiedInputName !== undefined) { - const inputsToStore: InitialInputs = initialInputData[directiveIndex] || - (initialInputData[directiveIndex] = ngDevMode ? new TNodeInitialData() : []); - inputsToStore.push(attrName as string, minifiedInputName, attrValue as string); + if (inputs.hasOwnProperty(attrName as string)) { + if (inputsToStore === null) inputsToStore = []; + inputsToStore.push(attrName as string, inputs[attrName as string], attrs[i + 1] as string); } i += 2; } - return initialInputData; + return inputsToStore; } //////////////////////////