refactor(core): remove unused embedded view instructions (#34715)
This commit performs a cleanup and removes unused embedded view instructions and corresponding tests. PR Close #34715
This commit is contained in:

committed by
Misko Hevery

parent
ed1b4a8f19
commit
0c8adbc4ec
@ -125,9 +125,6 @@ export {
|
||||
ɵɵclassProp,
|
||||
ɵɵComponentDefWithMeta,
|
||||
ɵɵcomponentHostSyntheticListener,
|
||||
ɵɵcontainer,
|
||||
ɵɵcontainerRefreshEnd,
|
||||
ɵɵcontainerRefreshStart,
|
||||
ɵɵcontentQuery,
|
||||
ɵɵCopyDefinitionFeature,
|
||||
ɵɵdefineComponent,
|
||||
@ -143,8 +140,6 @@ export {
|
||||
ɵɵelementContainerStart,
|
||||
ɵɵelementEnd,
|
||||
ɵɵelementStart,
|
||||
ɵɵembeddedViewEnd,
|
||||
ɵɵembeddedViewStart,
|
||||
ɵɵenableBindings,
|
||||
ɵɵFactoryDef,
|
||||
ɵɵgetCurrentView,
|
||||
|
@ -57,11 +57,6 @@ export function assertDataNext(lView: LView, index: number, arr?: any[]) {
|
||||
arr.length, index, `index ${index} expected to be at the end of arr (length ${arr.length})`);
|
||||
}
|
||||
|
||||
export function assertLContainerOrUndefined(value: any): asserts value is LContainer|undefined|
|
||||
null {
|
||||
value && assertEqual(isLContainer(value), true, 'Expecting LContainer or undefined or null');
|
||||
}
|
||||
|
||||
export function assertLContainer(value: any): asserts value is LContainer {
|
||||
assertDefined(value, 'LContainer must be defined');
|
||||
assertEqual(isLContainer(value), true, 'Expecting LContainer');
|
||||
|
@ -50,23 +50,15 @@ export {
|
||||
ɵɵclassProp,
|
||||
ɵɵcomponentHostSyntheticListener,
|
||||
|
||||
ɵɵcontainer,
|
||||
ɵɵcontainerRefreshEnd,
|
||||
ɵɵcontainerRefreshStart,
|
||||
|
||||
ɵɵdirectiveInject,
|
||||
|
||||
ɵɵelement,
|
||||
|
||||
ɵɵelementContainer,
|
||||
ɵɵelementContainerEnd,
|
||||
|
||||
ɵɵelementContainerStart,
|
||||
ɵɵelementEnd,
|
||||
|
||||
ɵɵelementStart,
|
||||
ɵɵembeddedViewEnd,
|
||||
|
||||
ɵɵembeddedViewStart,
|
||||
|
||||
ɵɵgetCurrentView,
|
||||
ɵɵhostProperty,
|
||||
|
@ -33,7 +33,6 @@ export * from './storage';
|
||||
export * from './di';
|
||||
export * from './element';
|
||||
export * from './element_container';
|
||||
export * from './embedded_view';
|
||||
export * from './get_current_view';
|
||||
export * from './listener';
|
||||
export * from './namespace';
|
||||
|
@ -5,46 +5,20 @@
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import {assertDataInRange, assertEqual} from '../../util/assert';
|
||||
import {assertFirstCreatePass, assertHasParent} from '../assert';
|
||||
import {assertFirstCreatePass} from '../assert';
|
||||
import {attachPatchData} from '../context_discovery';
|
||||
import {executeCheckHooks, executeInitAndCheckHooks, incrementInitPhaseFlags, registerPostOrderHooks} from '../hooks';
|
||||
import {ACTIVE_INDEX, CONTAINER_HEADER_OFFSET, LContainer} from '../interfaces/container';
|
||||
import {registerPostOrderHooks} from '../hooks';
|
||||
import {ComponentTemplate} from '../interfaces/definition';
|
||||
import {LocalRefExtractor, TAttributes, TContainerNode, TNode, TNodeType, TViewNode} from '../interfaces/node';
|
||||
import {LocalRefExtractor, TAttributes, TContainerNode, TNodeType, TViewNode} from '../interfaces/node';
|
||||
import {isDirectiveHost} from '../interfaces/type_checks';
|
||||
import {FLAGS, HEADER_OFFSET, InitPhaseState, LView, LViewFlags, RENDERER, T_HOST, TView, TViewType} from '../interfaces/view';
|
||||
import {assertNodeType} from '../node_assert';
|
||||
import {appendChild, removeView} from '../node_manipulation';
|
||||
import {getBindingIndex, getCheckNoChangesMode, getIsParent, getLView, getPreviousOrParentTNode, getTView, setIsNotParent, setPreviousOrParentTNode} from '../state';
|
||||
import {getConstant, getLContainerActiveIndex, load} from '../util/view_utils';
|
||||
import {HEADER_OFFSET, LView, RENDERER, T_HOST, TView, TViewType} from '../interfaces/view';
|
||||
import {appendChild} from '../node_manipulation';
|
||||
import {getLView, getTView, setPreviousOrParentTNode} from '../state';
|
||||
import {getConstant} from '../util/view_utils';
|
||||
|
||||
import {addToViewTree, createDirectivesInstances, createLContainer, createTNode, createTView, getOrCreateTNode, resolveDirectives, saveResolvedLocalsInData} from './shared';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates an LContainer for inline views, e.g.
|
||||
*
|
||||
* % if (showing) {
|
||||
* <div></div>
|
||||
* % }
|
||||
*
|
||||
* @param index The index of the container in the data array
|
||||
*
|
||||
* @codeGenApi
|
||||
*/
|
||||
export function ɵɵcontainer(index: number): void {
|
||||
const lView = getLView();
|
||||
const tView = getTView();
|
||||
const tNode = containerInternal(tView, lView, index, null, null);
|
||||
|
||||
if (tView.firstCreatePass) {
|
||||
tNode.tViews = [];
|
||||
}
|
||||
setIsNotParent();
|
||||
}
|
||||
|
||||
function templateFirstCreatePass(
|
||||
index: number, tView: TView, lView: LView, templateFn: ComponentTemplate<any>|null,
|
||||
decls: number, vars: number, tagName?: string|null, attrsIndex?: number|null,
|
||||
@ -121,97 +95,4 @@ export function ɵɵtemplate(
|
||||
if (localRefsIndex != null) {
|
||||
saveResolvedLocalsInData(lView, tNode, localRefExtractor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a container up to receive views.
|
||||
*
|
||||
* @param index The index of the container in the data array
|
||||
*
|
||||
* @codeGenApi
|
||||
*/
|
||||
export function ɵɵcontainerRefreshStart(index: number): void {
|
||||
const lView = getLView();
|
||||
const tView = getTView();
|
||||
let previousOrParentTNode = load(tView.data, index) as TNode;
|
||||
ngDevMode && assertNodeType(previousOrParentTNode, TNodeType.Container);
|
||||
setPreviousOrParentTNode(previousOrParentTNode, true);
|
||||
|
||||
lView[index + HEADER_OFFSET][ACTIVE_INDEX] = 0;
|
||||
|
||||
// We need to execute init hooks here so ngOnInit hooks are called in top level views
|
||||
// before they are called in embedded views (for backwards compatibility).
|
||||
if (!getCheckNoChangesMode()) {
|
||||
const hooksInitPhaseCompleted =
|
||||
(lView[FLAGS] & LViewFlags.InitPhaseStateMask) === InitPhaseState.InitPhaseCompleted;
|
||||
if (hooksInitPhaseCompleted) {
|
||||
const preOrderCheckHooks = tView.preOrderCheckHooks;
|
||||
if (preOrderCheckHooks !== null) {
|
||||
executeCheckHooks(lView, preOrderCheckHooks, null);
|
||||
}
|
||||
} else {
|
||||
const preOrderHooks = tView.preOrderHooks;
|
||||
if (preOrderHooks !== null) {
|
||||
executeInitAndCheckHooks(lView, preOrderHooks, InitPhaseState.OnInitHooksToBeRun, null);
|
||||
}
|
||||
incrementInitPhaseFlags(lView, InitPhaseState.OnInitHooksToBeRun);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the end of the LContainer.
|
||||
*
|
||||
* Marking the end of LContainer is the time when to child views get inserted or removed.
|
||||
*
|
||||
* @codeGenApi
|
||||
*/
|
||||
export function ɵɵcontainerRefreshEnd(): void {
|
||||
let previousOrParentTNode = getPreviousOrParentTNode();
|
||||
if (getIsParent()) {
|
||||
setIsNotParent();
|
||||
} else {
|
||||
ngDevMode && assertNodeType(previousOrParentTNode, TNodeType.View);
|
||||
ngDevMode && assertHasParent(previousOrParentTNode);
|
||||
previousOrParentTNode = previousOrParentTNode.parent!;
|
||||
setPreviousOrParentTNode(previousOrParentTNode, false);
|
||||
}
|
||||
|
||||
ngDevMode && assertNodeType(previousOrParentTNode, TNodeType.Container);
|
||||
|
||||
const lContainer: LContainer = getLView()[previousOrParentTNode.index];
|
||||
const nextIndex = getLContainerActiveIndex(lContainer);
|
||||
|
||||
// remove extra views at the end of the container
|
||||
while (nextIndex < lContainer.length - CONTAINER_HEADER_OFFSET) {
|
||||
removeView(lContainer, nextIndex);
|
||||
}
|
||||
}
|
||||
|
||||
function containerInternal(
|
||||
tView: TView, lView: LView, nodeIndex: number, tagName: string|null,
|
||||
attrs: TAttributes|null): TContainerNode {
|
||||
ngDevMode &&
|
||||
assertEqual(
|
||||
getBindingIndex(), tView.bindingStartIndex,
|
||||
'container nodes should be created before any bindings');
|
||||
|
||||
const adjustedIndex = nodeIndex + HEADER_OFFSET;
|
||||
ngDevMode && assertDataInRange(lView, nodeIndex + HEADER_OFFSET);
|
||||
ngDevMode && ngDevMode.rendererCreateComment++;
|
||||
const comment = lView[adjustedIndex] =
|
||||
lView[RENDERER].createComment(ngDevMode ? 'container' : '');
|
||||
const tNode =
|
||||
getOrCreateTNode(tView, lView[T_HOST], nodeIndex, TNodeType.Container, tagName, attrs);
|
||||
const lContainer = lView[adjustedIndex] = createLContainer(comment, lView, comment, tNode);
|
||||
|
||||
appendChild(tView, lView, comment, tNode);
|
||||
attachPatchData(comment, lView);
|
||||
|
||||
// Containers are added to the current view tree instead of their embedded views
|
||||
// because views can be removed and re-inserted.
|
||||
addToViewTree(lView, lContainer);
|
||||
|
||||
ngDevMode && assertNodeType(getPreviousOrParentTNode(), TNodeType.Container);
|
||||
return tNode;
|
||||
}
|
@ -1,145 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {assertDefined, assertEqual} from '../../util/assert';
|
||||
import {assertLContainerOrUndefined} from '../assert';
|
||||
import {ACTIVE_INDEX, ActiveIndexFlag, CONTAINER_HEADER_OFFSET, LContainer} from '../interfaces/container';
|
||||
import {RenderFlags} from '../interfaces/definition';
|
||||
import {TContainerNode, TNodeType} from '../interfaces/node';
|
||||
import {CONTEXT, LView, LViewFlags, PARENT, T_HOST, TVIEW, TView, TViewType} from '../interfaces/view';
|
||||
import {assertNodeType} from '../node_assert';
|
||||
import {insertView, removeView} from '../node_manipulation';
|
||||
import {enterView, getIsParent, getLView, getPreviousOrParentTNode, getTView, leaveView, setIsParent, setPreviousOrParentTNode} from '../state';
|
||||
import {getLContainerActiveIndex, isCreationMode} from '../util/view_utils';
|
||||
|
||||
import {assignTViewNodeToLView, createLView, createTView, refreshView, renderView} from './shared';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Marks the start of an embedded view.
|
||||
*
|
||||
* @param viewBlockId The ID of this view
|
||||
* @return boolean Whether or not this view is in creation mode
|
||||
*
|
||||
* @codeGenApi
|
||||
*/
|
||||
export function ɵɵembeddedViewStart(viewBlockId: number, decls: number, vars: number): RenderFlags {
|
||||
const lView = getLView();
|
||||
const previousOrParentTNode = getPreviousOrParentTNode();
|
||||
// The previous node can be a view node if we are processing an inline for loop
|
||||
const containerTNode = previousOrParentTNode.type === TNodeType.View ?
|
||||
previousOrParentTNode.parent! :
|
||||
previousOrParentTNode;
|
||||
const lContainer = lView[containerTNode.index] as LContainer;
|
||||
|
||||
ngDevMode && assertNodeType(containerTNode, TNodeType.Container);
|
||||
let viewToRender = scanForView(lContainer, getLContainerActiveIndex(lContainer), viewBlockId);
|
||||
|
||||
if (viewToRender) {
|
||||
setIsParent();
|
||||
enterView(viewToRender, viewToRender[TVIEW].node);
|
||||
} else {
|
||||
// When we create a new LView, we always reset the state of the instructions.
|
||||
viewToRender = createLView(
|
||||
lView, getOrCreateEmbeddedTView(viewBlockId, decls, vars, containerTNode as TContainerNode),
|
||||
null, LViewFlags.CheckAlways, null, null);
|
||||
|
||||
const tParentNode = getIsParent() ? previousOrParentTNode :
|
||||
previousOrParentTNode && previousOrParentTNode.parent;
|
||||
assignTViewNodeToLView(viewToRender[TVIEW], tParentNode, viewBlockId, viewToRender);
|
||||
enterView(viewToRender, viewToRender[TVIEW].node);
|
||||
}
|
||||
if (lContainer) {
|
||||
if (isCreationMode(viewToRender)) {
|
||||
// it is a new view, insert it into collection of views for a given container
|
||||
insertView(
|
||||
viewToRender[TVIEW], viewToRender, lContainer, getLContainerActiveIndex(lContainer));
|
||||
}
|
||||
lContainer[ACTIVE_INDEX] += ActiveIndexFlag.INCREMENT;
|
||||
}
|
||||
return isCreationMode(viewToRender) ? RenderFlags.Create | RenderFlags.Update :
|
||||
RenderFlags.Update;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the TView (e.g. static data) for the active embedded view.
|
||||
*
|
||||
* Each embedded view block must create or retrieve its own TView. Otherwise, the embedded view's
|
||||
* static data for a particular node would overwrite the static data for a node in the view above
|
||||
* it with the same index (since it's in the same template).
|
||||
*
|
||||
* @param viewIndex The index of the TView in TNode.tViews
|
||||
* @param decls The number of nodes, local refs, and pipes in this template
|
||||
* @param vars The number of bindings and pure function bindings in this template
|
||||
* @param container The parent container in which to look for the view's static data
|
||||
* @returns TView
|
||||
*/
|
||||
function getOrCreateEmbeddedTView(
|
||||
viewIndex: number, decls: number, vars: number, parent: TContainerNode): TView {
|
||||
const tView = getLView()[TVIEW];
|
||||
ngDevMode && assertNodeType(parent, TNodeType.Container);
|
||||
const containerTViews = parent.tViews as TView[];
|
||||
ngDevMode && assertDefined(containerTViews, 'TView expected');
|
||||
ngDevMode && assertEqual(Array.isArray(containerTViews), true, 'TViews should be in an array');
|
||||
if (viewIndex >= containerTViews.length || containerTViews[viewIndex] == null) {
|
||||
containerTViews[viewIndex] = createTView(
|
||||
TViewType.Embedded, viewIndex, null, decls, vars, tView.directiveRegistry,
|
||||
tView.pipeRegistry, null, null, tView.consts);
|
||||
}
|
||||
return containerTViews[viewIndex];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Looks for a view with a given view block id inside a provided LContainer.
|
||||
* Removes views that need to be deleted in the process.
|
||||
*
|
||||
* @param lContainer to search for views
|
||||
* @param startIdx starting index in the views array to search from
|
||||
* @param viewBlockId exact view block id to look for
|
||||
*/
|
||||
function scanForView(lContainer: LContainer, startIdx: number, viewBlockId: number): LView|null {
|
||||
for (let i = startIdx + CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
|
||||
const viewAtPositionId = lContainer[i][TVIEW].id;
|
||||
if (viewAtPositionId === viewBlockId) {
|
||||
return lContainer[i];
|
||||
} else if (viewAtPositionId < viewBlockId) {
|
||||
// found a view that should not be at this position - remove
|
||||
removeView(lContainer, i - CONTAINER_HEADER_OFFSET);
|
||||
} else {
|
||||
// found a view with id greater than the one we are searching for
|
||||
// which means that required view doesn't exist and can't be found at
|
||||
// later positions in the views array - stop the searchdef.cont here
|
||||
break;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the end of an embedded view.
|
||||
*
|
||||
* @codeGenApi
|
||||
*/
|
||||
export function ɵɵembeddedViewEnd(): void {
|
||||
const lView = getLView();
|
||||
const tView = getTView();
|
||||
const viewHost = lView[T_HOST];
|
||||
const context = lView[CONTEXT];
|
||||
|
||||
if (isCreationMode(lView)) {
|
||||
renderView(tView, lView, context); // creation mode pass
|
||||
}
|
||||
refreshView(tView, lView, tView.template, context); // update mode pass
|
||||
|
||||
const lContainer = lView[PARENT] as LContainer;
|
||||
ngDevMode && assertLContainerOrUndefined(lContainer);
|
||||
leaveView();
|
||||
setPreviousOrParentTNode(viewHost!, false);
|
||||
}
|
@ -20,6 +20,7 @@ import {HOST, LView, NEXT, PARENT, T_HOST, TRANSPLANTED_VIEWS_TO_REFRESH} from '
|
||||
* `LContainer`.
|
||||
*/
|
||||
export const TYPE = 1;
|
||||
|
||||
/**
|
||||
* Below are constants for LContainer indices to help us look up LContainer members
|
||||
* without having to remember the specific indices.
|
||||
@ -48,9 +49,7 @@ export const CONTAINER_HEADER_OFFSET = 10;
|
||||
|
||||
|
||||
/**
|
||||
* Used to track:
|
||||
* - Inline embedded views (see: `ɵɵembeddedViewStart`)
|
||||
* - Transplanted `LView`s (see: `LView[DECLARATION_COMPONENT_VIEW])`
|
||||
* Used to track Transplanted `LView`s (see: `LView[DECLARATION_COMPONENT_VIEW])`
|
||||
*/
|
||||
export const enum ActiveIndexFlag {
|
||||
/**
|
||||
@ -72,13 +71,6 @@ export const enum ActiveIndexFlag {
|
||||
* Number of bits to shift inline embedded views counter to make space for other flags.
|
||||
*/
|
||||
SHIFT = 1,
|
||||
|
||||
|
||||
/**
|
||||
* When incrementing the active index for inline embedded views, the amount to increment to leave
|
||||
* space for other flags.
|
||||
*/
|
||||
INCREMENT = 1 << SHIFT,
|
||||
}
|
||||
|
||||
/**
|
||||
@ -111,10 +103,6 @@ export interface LContainer extends Array<any> {
|
||||
* 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.
|
||||
*
|
||||
* This is used by `ɵɵembeddedViewStart` to track which `LView` is currently active.
|
||||
* Because `ɵɵembeddedViewStart` is not generated by the compiler this feature is essentially
|
||||
* unused.
|
||||
*
|
||||
* The lowest bit signals that this `LContainer` has transplanted views which need to be change
|
||||
* detected as part of the declaration CD. (See `LView[DECLARATION_COMPONENT_VIEW]`)
|
||||
*/
|
||||
|
@ -49,10 +49,7 @@ export const angularCoreEnv: {[name: string]: Function} =
|
||||
'ɵɵProvidersFeature': r3.ɵɵProvidersFeature,
|
||||
'ɵɵCopyDefinitionFeature': r3.ɵɵCopyDefinitionFeature,
|
||||
'ɵɵInheritDefinitionFeature': r3.ɵɵInheritDefinitionFeature,
|
||||
'ɵɵcontainer': r3.ɵɵcontainer,
|
||||
'ɵɵnextContext': r3.ɵɵnextContext,
|
||||
'ɵɵcontainerRefreshStart': r3.ɵɵcontainerRefreshStart,
|
||||
'ɵɵcontainerRefreshEnd': r3.ɵɵcontainerRefreshEnd,
|
||||
'ɵɵnamespaceHTML': r3.ɵɵnamespaceHTML,
|
||||
'ɵɵnamespaceMathML': r3.ɵɵnamespaceMathML,
|
||||
'ɵɵnamespaceSVG': r3.ɵɵnamespaceSVG,
|
||||
@ -152,8 +149,6 @@ export const angularCoreEnv: {[name: string]: Function} =
|
||||
'ɵɵtextInterpolate7': r3.ɵɵtextInterpolate7,
|
||||
'ɵɵtextInterpolate8': r3.ɵɵtextInterpolate8,
|
||||
'ɵɵtextInterpolateV': r3.ɵɵtextInterpolateV,
|
||||
'ɵɵembeddedViewStart': r3.ɵɵembeddedViewStart,
|
||||
'ɵɵembeddedViewEnd': r3.ɵɵembeddedViewEnd,
|
||||
'ɵɵi18n': r3.ɵɵi18n,
|
||||
'ɵɵi18nAttributes': r3.ɵɵi18nAttributes,
|
||||
'ɵɵi18nExp': r3.ɵɵi18nExp,
|
||||
|
Reference in New Issue
Block a user