From 01cf04c85fd93354339c589ef520c8c480ea6073 Mon Sep 17 00:00:00 2001 From: Misko Hevery Date: Wed, 15 May 2019 21:08:31 -0700 Subject: [PATCH] refactor(ivy): createNodeAtIndex links TNodes on first pass only (#30453) PR Close #30453 --- .../core/src/render3/instructions/shared.ts | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/packages/core/src/render3/instructions/shared.ts b/packages/core/src/render3/instructions/shared.ts index 43dfcefe84..d94795fc78 100644 --- a/packages/core/src/render3/instructions/shared.ts +++ b/packages/core/src/render3/instructions/shared.ts @@ -253,10 +253,9 @@ export function createNodeAtIndex( const lView = getLView(); const tView = lView[TVIEW]; const adjustedIndex = index + HEADER_OFFSET; - - const previousOrParentTNode = getPreviousOrParentTNode(); let tNode = tView.data[adjustedIndex] as TNode; if (tNode == null) { + const previousOrParentTNode = getPreviousOrParentTNode(); const isParent = getIsParent(); const parent = isParent ? previousOrParentTNode : previousOrParentTNode && previousOrParentTNode.parent; @@ -369,7 +368,8 @@ export function createEmbeddedViewAndNode( * * Dynamically created views must store/retrieve their TViews differently from component views * because their template functions are nested in the template functions of their hosts, creating - * closures. If their host template happens to be an embedded template in a loop (e.g. ngFor inside + * closures. If their host template happens to be an embedded template in a loop (e.g. ngFor + * inside * an ngFor), the nesting would mean we'd have multiple instances of the template function, so we * can't store TViews in the template function itself (as we do for comps). Instead, we store the * TView for dynamically created views on their host TNode, which only has one instance. @@ -811,7 +811,8 @@ export function elementPropertyInternal( savePropertyDebugData(tNode, lView, propName, lView[TVIEW].data, nativeOnly); const renderer = loadRendererFn ? loadRendererFn(tNode, lView) : lView[RENDERER]; - // It is assumed that the sanitizer is only added when the compiler determines that the property + // It is assumed that the sanitizer is only added when the compiler determines that the + // property // is risky, so sanitization can be done without further checks. value = sanitizer != null ? (sanitizer(value, tNode.tagName || '', propName) as any) : value; if (isProceduralRenderer(renderer)) { @@ -957,7 +958,8 @@ export function instantiateRootComponent( function resolveDirectives( tView: TView, viewData: LView, directives: DirectiveDef[] | null, tNode: TNode, localRefs: string[] | null): void { - // Please make sure to have explicit type for `exportsMap`. Inferred type triggers bug in tsickle. + // Please make sure to have explicit type for `exportsMap`. Inferred type triggers bug in + // tsickle. ngDevMode && assertEqual(tView.firstTemplatePass, true, 'should run on first template pass only'); const exportsMap: ({[key: string]: number} | null) = localRefs ? {'': -1} : null; if (directives) { @@ -1383,7 +1385,8 @@ export function createLContainer( /** - * Goes over dynamic embedded views (ones created through ViewContainerRef APIs) and refreshes them + * Goes over dynamic embedded views (ones created through ViewContainerRef APIs) and refreshes + * them * by executing an associated template function. */ function refreshDynamicEmbeddedViews(lView: LView) { @@ -1394,7 +1397,8 @@ function refreshDynamicEmbeddedViews(lView: LView) { if (current[ACTIVE_INDEX] === -1 && isLContainer(current)) { for (let i = CONTAINER_HEADER_OFFSET; i < current.length; i++) { const dynamicViewData = current[i]; - // The directives and pipes are not needed here as an existing view is only being refreshed. + // The directives and pipes are not needed here as an existing view is only being + // refreshed. ngDevMode && assertDefined(dynamicViewData[TVIEW], 'TView must be allocated'); renderEmbeddedTemplate(dynamicViewData, dynamicViewData[TVIEW], dynamicViewData[CONTEXT] !); } @@ -1471,9 +1475,12 @@ function syncViewWithBlueprint(componentView: LView) { * @returns The state passed in */ export function addToViewTree(lView: LView, lViewOrLContainer: T): T { - // TODO(benlesh/misko): This implementation is incorrect, because it always adds the LContainer to - // the end of the queue, which means if the developer retrieves the LContainers from RNodes out of - // order, the change detection will run out of order, as the act of retrieving the the LContainer + // TODO(benlesh/misko): This implementation is incorrect, because it always adds the LContainer + // to + // the end of the queue, which means if the developer retrieves the LContainers from RNodes out + // of + // order, the change detection will run out of order, as the act of retrieving the the + // LContainer // from the RNode is what adds it to the queue. if (lView[CHILD_HEAD]) { lView[CHILD_TAIL] ![NEXT] = lViewOrLContainer; @@ -1626,7 +1633,8 @@ export function checkNoChangesInRootView(lView: LView): void { } } -/** Checks the view of the component provided. Does not gate on dirty checks or execute doCheck. */ +/** Checks the view of the component provided. Does not gate on dirty checks or execute doCheck. + */ export function checkView(hostView: LView, component: T) { const hostTView = hostView[TVIEW]; const oldView = enterView(hostView, hostView[T_HOST]);