diff --git a/packages/core/src/render3/di.ts b/packages/core/src/render3/di.ts index b57926f254..f5a0f82c1e 100644 --- a/packages/core/src/render3/di.ts +++ b/packages/core/src/render3/di.ts @@ -572,7 +572,7 @@ export function getOrCreateContainerRef(di: LInjector): viewEngine_ViewContainer ngDevMode && assertNodeOfPossibleTypes(vcRefHost, TNodeType.Container, TNodeType.Element); const hostParent = getParentLNode(vcRefHost) !; - const lContainer = createLContainer(hostParent, vcRefHost.view); + const lContainer = createLContainer(hostParent, vcRefHost.view, undefined, true); const lContainerNode: LContainerNode = createLNodeObject( TNodeType.Container, vcRefHost.view, hostParent, undefined, lContainer, null); @@ -644,19 +644,6 @@ class ViewContainerRef implements viewEngine_ViewContainerRef { this._viewRefs.splice(adjustedIdx, 0, viewRef); - // If the view is dynamic (has a template), it needs to be counted both at the container - // level and at the node above the container. - if (lViewNode.data.template !== null) { - // Increment the container view count. - this._lContainerNode.data.dynamicViewCount++; - - // Look for the parent node and increment its dynamic view count. - const containerParent = getParentLNode(this._lContainerNode) as LElementNode; - if (containerParent !== null && containerParent.data !== null) { - ngDevMode && assertNodeOfPossibleTypes(containerParent, TNodeType.View, TNodeType.Element); - containerParent.data.dynamicViewCount++; - } - } return viewRef; } diff --git a/packages/core/src/render3/instructions.ts b/packages/core/src/render3/instructions.ts index 20752d436a..cc178c2eb0 100644 --- a/packages/core/src/render3/instructions.ts +++ b/packages/core/src/render3/instructions.ts @@ -321,7 +321,6 @@ export function createLView( bindingIndex: -1, template: template, context: context, - dynamicViewCount: 0, lifecycleStage: LifecycleStage.Init, queries: null, injector: currentView && currentView.injector, @@ -1455,19 +1454,28 @@ function generateInitialInputs( //// ViewContainer & View ////////////////////////// +/** + * Creates a LContainer, either from a container instruction, or for a ViewContainerRef. + * + * @param parentLNode the LNode in which the container's content will be rendered + * @param currentView The parent view of the LContainer + * @param template Optional the inline template (ng-template instruction case) + * @param isForViewContainerRef Optional a flag indicating the ViewContainerRef case + * @returns LContainer + */ export function createLContainer( - parentLNode: LNode, currentView: LView, template?: ComponentTemplate): LContainer { + parentLNode: LNode, currentView: LView, template?: ComponentTemplate, + isForViewContainerRef?: boolean): LContainer { ngDevMode && assertNotNull(parentLNode, 'containers should have a parent'); return { views: [], - nextIndex: 0, + nextIndex: isForViewContainerRef ? null : 0, // If the direct parent of the container is a view, its views will need to be added // through insertView() when its parent view is being inserted: renderParent: canInsertNativeNode(parentLNode, currentView) ? parentLNode : null, template: template == null ? null : template, next: null, parent: currentView, - dynamicViewCount: 0, queries: null }; } @@ -1553,7 +1561,7 @@ export function containerRefreshEnd(): void { const container = previousOrParentNode as LContainerNode; container.native = undefined; ngDevMode && assertNodeType(container, TNodeType.Container); - const nextIndex = container.data.nextIndex; + const nextIndex = container.data.nextIndex !; // remove extra views at the end of the container while (nextIndex < container.data.views.length) { @@ -1563,7 +1571,9 @@ export function containerRefreshEnd(): void { function refreshDynamicChildren() { for (let current = currentView.child; current !== null; current = current.next) { - if (current.dynamicViewCount !== 0 && (current as LContainer).views) { + // Note: current can be a LView or a LContainer, but here we are only interested in LContainer. + // The distinction is made because nextIndex and views do not exist on LView. + if (isLContainer(current)) { const container = current as LContainer; for (let i = 0; i < container.views.length; i++) { const lViewNode = container.views[i]; @@ -1577,6 +1587,10 @@ function refreshDynamicChildren() { } } +function isLContainer(node: LView | LContainer): node is LContainer { + return (node as LContainer).nextIndex == null && (node as LContainer).views != null; +} + /** * Looks for a view with a given view block id inside a provided LContainer. * Removes views that need to be deleted in the process. @@ -1617,7 +1631,7 @@ export function embeddedViewStart(viewBlockId: number): RenderFlags { (isParent ? previousOrParentNode : getParentLNode(previousOrParentNode)) as LContainerNode; ngDevMode && assertNodeType(container, TNodeType.Container); const lContainer = container.data; - let viewNode: LViewNode|null = scanForView(container, lContainer.nextIndex, viewBlockId); + let viewNode: LViewNode|null = scanForView(container, lContainer.nextIndex !, viewBlockId); if (viewNode) { previousOrParentNode = viewNode; @@ -1630,7 +1644,7 @@ export function embeddedViewStart(viewBlockId: number): RenderFlags { viewBlockId, renderer, getOrCreateEmbeddedTView(viewBlockId, container), null, null, LViewFlags.CheckAlways, getCurrentSanitizer()); if (lContainer.queries) { - newView.queries = lContainer.queries.enterView(lContainer.nextIndex); + newView.queries = lContainer.queries.enterView(lContainer.nextIndex !); } enterView( @@ -1678,10 +1692,10 @@ export function embeddedViewEnd(): void { // used by the ViewContainerRef must be set. setRenderParentInProjectedNodes(lContainer.renderParent, viewNode); // it is a new view, insert it into collection of views for a given container - insertView(containerNode, viewNode, lContainer.nextIndex); + insertView(containerNode, viewNode, lContainer.nextIndex !); } - lContainer.nextIndex++; + lContainer.nextIndex !++; } leaveView(currentView !.parent !); ngDevMode && assertEqual(isParent, false, 'isParent'); diff --git a/packages/core/src/render3/interfaces/container.ts b/packages/core/src/render3/interfaces/container.ts index be4fedb11b..54cb538d7d 100644 --- a/packages/core/src/render3/interfaces/container.ts +++ b/packages/core/src/render3/interfaces/container.ts @@ -18,8 +18,11 @@ export interface LContainer { /** * The next active index in the views array to read or write to. This helps us * keep track of where we are in the views array. + * In the case the LContainer is created for a ViewContainerRef, + * it is set to null to identify this scenario, as indices are "absolute" in that case, + * i.e. provided directly by the user of the ViewContainerRef API. */ - nextIndex: number; + nextIndex: number|null; /** * This allows us to jump from a container to a sibling container or @@ -69,12 +72,6 @@ export interface LContainer { */ readonly template: ComponentTemplate|null; - /** - * A count of dynamic views rendered into this container. If this is non-zero, the `views` array - * will be traversed when refreshing dynamic views on this container. - */ - dynamicViewCount: number; - /** * Queries active for this container - all the views inserted to / removed from * this container are reported to queries referenced here. diff --git a/packages/core/src/render3/interfaces/view.ts b/packages/core/src/render3/interfaces/view.ts index a405cdde93..a234389f4a 100644 --- a/packages/core/src/render3/interfaces/view.ts +++ b/packages/core/src/render3/interfaces/view.ts @@ -181,14 +181,6 @@ export interface LView { */ context: {}|RootContext|null; - /** - * A count of dynamic views that are children of this view (indirectly via containers). - * - * This is used to decide whether to scan children of this view when refreshing dynamic views - * after refreshing the view itself. - */ - dynamicViewCount: number; - /** * Queries active for this view - nodes from a view are reported to those queries */ diff --git a/packages/core/test/bundling/hello_world/bundle.golden_symbols.json b/packages/core/test/bundling/hello_world/bundle.golden_symbols.json index 3a97e3864e..77abaff7ae 100644 --- a/packages/core/test/bundling/hello_world/bundle.golden_symbols.json +++ b/packages/core/test/bundling/hello_world/bundle.golden_symbols.json @@ -125,6 +125,9 @@ { "name": "invertObject" }, + { + "name": "isLContainer" + }, { "name": "isProceduralRenderer" }, diff --git a/packages/core/test/bundling/todo/bundle.golden_symbols.json b/packages/core/test/bundling/todo/bundle.golden_symbols.json index 34d33906bc..11389750f7 100644 --- a/packages/core/test/bundling/todo/bundle.golden_symbols.json +++ b/packages/core/test/bundling/todo/bundle.golden_symbols.json @@ -494,6 +494,9 @@ { "name": "isJsObject" }, + { + "name": "isLContainer" + }, { "name": "isListLikeIterable" },