refactor(ivy): replace enter / leave view with selectView (#32263)

After a series of recent refactorings `enterView` and `leaveView` became
identical. This PR merges both into one concept of view selectio (similar
to a node selection). This reduces number of concepts and code size.

PR Close #32263
This commit is contained in:
Pawel Kozlowski 2019-08-22 11:43:24 +02:00 committed by atscott
parent e3422e0aed
commit e63a7b0532
10 changed files with 35 additions and 54 deletions

View File

@ -23,7 +23,7 @@ import {TElementNode, TNode, TNodeType} from './interfaces/node';
import {PlayerHandler} from './interfaces/player'; import {PlayerHandler} from './interfaces/player';
import {RElement, Renderer3, RendererFactory3, domRendererFactory3} from './interfaces/renderer'; import {RElement, Renderer3, RendererFactory3, domRendererFactory3} from './interfaces/renderer';
import {CONTEXT, HEADER_OFFSET, LView, LViewFlags, RootContext, RootContextFlags, TVIEW} from './interfaces/view'; import {CONTEXT, HEADER_OFFSET, LView, LViewFlags, RootContext, RootContextFlags, TVIEW} from './interfaces/view';
import {enterView, getPreviousOrParentTNode, leaveView, resetComponentState, setActiveHostElement} from './state'; import {getPreviousOrParentTNode, resetComponentState, selectView, setActiveHostElement} from './state';
import {publishDefaultGlobalUtils} from './util/global_utils'; import {publishDefaultGlobalUtils} from './util/global_utils';
import {defaultScheduler, stringifyForError} from './util/misc_utils'; import {defaultScheduler, stringifyForError} from './util/misc_utils';
import {getRootContext} from './util/view_traversal_utils'; import {getRootContext} from './util/view_traversal_utils';
@ -133,7 +133,7 @@ export function renderComponent<T>(
null, rootTView, rootContext, rootFlags, null, null, rendererFactory, renderer, undefined, null, rootTView, rootContext, rootFlags, null, null, rendererFactory, renderer, undefined,
opts.injector || null); opts.injector || null);
const oldView = enterView(rootView, null); const oldView = selectView(rootView, null);
let component: T; let component: T;
try { try {
@ -149,7 +149,7 @@ export function renderComponent<T>(
refreshView(rootView, rootTView, null, null); refreshView(rootView, rootTView, null, null);
} finally { } finally {
leaveView(oldView); selectView(oldView, null);
if (rendererFactory.end) rendererFactory.end(); if (rendererFactory.end) rendererFactory.end();
} }

View File

@ -29,7 +29,7 @@ import {ComponentDef} from './interfaces/definition';
import {TContainerNode, TElementContainerNode, TElementNode} from './interfaces/node'; import {TContainerNode, TElementContainerNode, TElementNode} from './interfaces/node';
import {RNode, RendererFactory3, domRendererFactory3, isProceduralRenderer} from './interfaces/renderer'; import {RNode, RendererFactory3, domRendererFactory3, isProceduralRenderer} from './interfaces/renderer';
import {LView, LViewFlags, TVIEW} from './interfaces/view'; import {LView, LViewFlags, TVIEW} from './interfaces/view';
import {enterView, leaveView, namespaceHTMLInternal} from './state'; import {namespaceHTMLInternal, selectView} from './state';
import {defaultScheduler} from './util/misc_utils'; import {defaultScheduler} from './util/misc_utils';
import {getTNode} from './util/view_utils'; import {getTNode} from './util/view_utils';
import {createElementRef} from './view_engine_compatibility'; import {createElementRef} from './view_engine_compatibility';
@ -167,7 +167,7 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
rootViewInjector); rootViewInjector);
// rootView is the parent when bootstrapping // rootView is the parent when bootstrapping
const oldLView = enterView(rootLView, null); const oldLView = selectView(rootLView, null);
let component: T; let component: T;
let tElementNode: TElementNode; let tElementNode: TElementNode;
@ -194,7 +194,7 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
renderView(rootLView, rootTView, null); renderView(rootLView, rootTView, null);
} finally { } finally {
leaveView(oldLView); selectView(oldLView, null);
} }
const componentRef = new ComponentRef( const componentRef = new ComponentRef(

View File

@ -14,7 +14,7 @@ import {TContainerNode, TNodeType} from '../interfaces/node';
import {CONTEXT, LView, LViewFlags, PARENT, TVIEW, TView, T_HOST} from '../interfaces/view'; import {CONTEXT, LView, LViewFlags, PARENT, TVIEW, TView, T_HOST} from '../interfaces/view';
import {assertNodeType} from '../node_assert'; import {assertNodeType} from '../node_assert';
import {insertView, removeView} from '../node_manipulation'; import {insertView, removeView} from '../node_manipulation';
import {enterView, getIsParent, getLView, getPreviousOrParentTNode, leaveView, setIsParent, setPreviousOrParentTNode} from '../state'; import {getIsParent, getLView, getPreviousOrParentTNode, selectView, setIsParent, setPreviousOrParentTNode} from '../state';
import {isCreationMode} from '../util/view_utils'; import {isCreationMode} from '../util/view_utils';
import {assignTViewNodeToLView, createLView, createTView, refreshView, renderView} from './shared'; import {assignTViewNodeToLView, createLView, createTView, refreshView, renderView} from './shared';
@ -43,7 +43,7 @@ export function ɵɵembeddedViewStart(
if (viewToRender) { if (viewToRender) {
setIsParent(); setIsParent();
enterView(viewToRender, viewToRender[TVIEW].node); selectView(viewToRender, viewToRender[TVIEW].node);
} else { } else {
// When we create a new LView, we always reset the state of the instructions. // When we create a new LView, we always reset the state of the instructions.
viewToRender = createLView( viewToRender = createLView(
@ -54,7 +54,7 @@ export function ɵɵembeddedViewStart(
const tParentNode = getIsParent() ? previousOrParentTNode : const tParentNode = getIsParent() ? previousOrParentTNode :
previousOrParentTNode && previousOrParentTNode.parent; previousOrParentTNode && previousOrParentTNode.parent;
assignTViewNodeToLView(viewToRender[TVIEW], tParentNode, viewBlockId, viewToRender); assignTViewNodeToLView(viewToRender[TVIEW], tParentNode, viewBlockId, viewToRender);
enterView(viewToRender, viewToRender[TVIEW].node); selectView(viewToRender, viewToRender[TVIEW].node);
} }
if (lContainer) { if (lContainer) {
if (isCreationMode(viewToRender)) { if (isCreationMode(viewToRender)) {
@ -139,6 +139,6 @@ export function ɵɵembeddedViewEnd(): void {
const lContainer = lView[PARENT] as LContainer; const lContainer = lView[PARENT] as LContainer;
ngDevMode && assertLContainerOrUndefined(lContainer); ngDevMode && assertLContainerOrUndefined(lContainer);
leaveView(lContainer[PARENT] !); selectView(lContainer[PARENT] !, null);
setPreviousOrParentTNode(viewHost !, false); setPreviousOrParentTNode(viewHost !, false);
} }

View File

@ -28,7 +28,7 @@ import {isComponent, isComponentDef, isContentQueryHost, isLContainer, isRootVie
import {BINDING_INDEX, CHILD_HEAD, CHILD_TAIL, CLEANUP, CONTEXT, DECLARATION_VIEW, ExpandoInstructions, FLAGS, HEADER_OFFSET, HOST, INJECTOR, InitPhaseState, LView, LViewFlags, NEXT, PARENT, RENDERER, RENDERER_FACTORY, RootContext, RootContextFlags, SANITIZER, TData, TVIEW, TView, T_HOST} from '../interfaces/view'; import {BINDING_INDEX, CHILD_HEAD, CHILD_TAIL, CLEANUP, CONTEXT, DECLARATION_VIEW, ExpandoInstructions, FLAGS, HEADER_OFFSET, HOST, INJECTOR, InitPhaseState, LView, LViewFlags, NEXT, PARENT, RENDERER, RENDERER_FACTORY, RootContext, RootContextFlags, SANITIZER, TData, TVIEW, TView, T_HOST} from '../interfaces/view';
import {assertNodeOfPossibleTypes} from '../node_assert'; import {assertNodeOfPossibleTypes} from '../node_assert';
import {isNodeMatchingSelectorList} from '../node_selector_matcher'; import {isNodeMatchingSelectorList} from '../node_selector_matcher';
import {enterView, getBindingsEnabled, getCheckNoChangesMode, getIsParent, getLView, getPreviousOrParentTNode, getSelectedIndex, incrementActiveDirectiveId, leaveView, namespaceHTMLInternal, setActiveHostElement, setBindingRoot, setCheckNoChangesMode, setCurrentDirectiveDef, setCurrentQueryIndex, setPreviousOrParentTNode, setSelectedIndex} from '../state'; import {getBindingsEnabled, getCheckNoChangesMode, getIsParent, getLView, getPreviousOrParentTNode, getSelectedIndex, incrementActiveDirectiveId, namespaceHTMLInternal, selectView, setActiveHostElement, setBindingRoot, setCheckNoChangesMode, setCurrentDirectiveDef, setCurrentQueryIndex, setPreviousOrParentTNode, setSelectedIndex} from '../state';
import {renderStylingMap} from '../styling_next/bindings'; import {renderStylingMap} from '../styling_next/bindings';
import {NO_CHANGE} from '../tokens'; import {NO_CHANGE} from '../tokens';
import {ANIMATION_PROP_PREFIX, isAnimationProp} from '../util/attrs_utils'; import {ANIMATION_PROP_PREFIX, isAnimationProp} from '../util/attrs_utils';
@ -312,7 +312,7 @@ export function allocExpando(view: LView, numSlotsToAlloc: number) {
*/ */
export function renderView<T>(lView: LView, tView: TView, context: T): void { export function renderView<T>(lView: LView, tView: TView, context: T): void {
ngDevMode && assertEqual(isCreationMode(lView), true, 'Should be run in creation mode'); ngDevMode && assertEqual(isCreationMode(lView), true, 'Should be run in creation mode');
const oldView = enterView(lView, lView[T_HOST]); const oldView = selectView(lView, lView[T_HOST]);
try { try {
const viewQuery = tView.viewQuery; const viewQuery = tView.viewQuery;
if (viewQuery !== null) { if (viewQuery !== null) {
@ -357,7 +357,7 @@ export function renderView<T>(lView: LView, tView: TView, context: T): void {
} finally { } finally {
lView[FLAGS] &= ~LViewFlags.CreationMode; lView[FLAGS] &= ~LViewFlags.CreationMode;
leaveView(oldView); selectView(oldView, null);
} }
} }
@ -372,7 +372,7 @@ export function renderView<T>(lView: LView, tView: TView, context: T): void {
export function refreshView<T>( export function refreshView<T>(
lView: LView, tView: TView, templateFn: ComponentTemplate<{}>| null, context: T) { lView: LView, tView: TView, templateFn: ComponentTemplate<{}>| null, context: T) {
ngDevMode && assertEqual(isCreationMode(lView), false, 'Should be run in update mode'); ngDevMode && assertEqual(isCreationMode(lView), false, 'Should be run in update mode');
const oldView = enterView(lView, lView[T_HOST]); const oldView = selectView(lView, lView[T_HOST]);
const flags = lView[FLAGS]; const flags = lView[FLAGS];
try { try {
resetPreOrderHookFlags(lView); resetPreOrderHookFlags(lView);
@ -460,7 +460,7 @@ export function refreshView<T>(
} finally { } finally {
lView[FLAGS] &= ~(LViewFlags.Dirty | LViewFlags.FirstLViewPass); lView[FLAGS] &= ~(LViewFlags.Dirty | LViewFlags.FirstLViewPass);
leaveView(oldView); selectView(oldView, null);
} }
} }

View File

@ -400,18 +400,18 @@ export function setCurrentQueryIndex(value: number): void {
} }
/** /**
* Swap the current state with a new state. * Swap the current lView with a new lView.
* *
* For performance reasons we store the state in the top level of the module. * For performance reasons we store the lView in the top level of the module.
* This way we minimize the number of properties to read. Whenever a new view * This way we minimize the number of properties to read. Whenever a new view
* is entered we have to store the state for later, and when the view is * is entered we have to store the lView for later, and when the view is
* exited the state has to be restored * exited the state has to be restored
* *
* @param newView New state to become active * @param newView New lView to become active
* @param host Element to which the View is a child of * @param host Element to which the View is a child of
* @returns the previous state; * @returns the previously active lView;
*/ */
export function enterView(newView: LView, hostTNode: TElementNode | TViewNode | null): LView { export function selectView(newView: LView, hostTNode: TElementNode | TViewNode | null): LView {
ngDevMode && assertLViewOrUndefined(newView); ngDevMode && assertLViewOrUndefined(newView);
const oldView = lView; const oldView = lView;
@ -450,16 +450,6 @@ export function resetComponentState() {
resetAllStylingState(); resetAllStylingState();
} }
/**
* Used in lieu of enterView to make it clear when we are exiting a child view. This makes
* the direction of traversal (up or down the view tree) a bit clearer.
*
* @param newView New LView to become active
*/
export function leaveView(newView: LView): void {
enterView(newView, null);
}
let _selectedIndex = -1; let _selectedIndex = -1;
/** /**

View File

@ -248,9 +248,6 @@
{ {
"name": "elementCreate" "name": "elementCreate"
}, },
{
"name": "enterView"
},
{ {
"name": "executeCheckHooks" "name": "executeCheckHooks"
}, },
@ -488,9 +485,6 @@
{ {
"name": "isStylingValueDefined" "name": "isStylingValueDefined"
}, },
{
"name": "leaveView"
},
{ {
"name": "locateHostElement" "name": "locateHostElement"
}, },
@ -596,6 +590,9 @@
{ {
"name": "selectInternal" "name": "selectInternal"
}, },
{
"name": "selectView"
},
{ {
"name": "setActiveHostElement" "name": "setActiveHostElement"
}, },

View File

@ -206,9 +206,6 @@
{ {
"name": "domRendererFactory3" "name": "domRendererFactory3"
}, },
{
"name": "enterView"
},
{ {
"name": "executeCheckHooks" "name": "executeCheckHooks"
}, },
@ -359,9 +356,6 @@
{ {
"name": "isRootView" "name": "isRootView"
}, },
{
"name": "leaveView"
},
{ {
"name": "locateHostElement" "name": "locateHostElement"
}, },
@ -437,6 +431,9 @@
{ {
"name": "selectInternal" "name": "selectInternal"
}, },
{
"name": "selectView"
},
{ {
"name": "setActiveHostElement" "name": "setActiveHostElement"
}, },

View File

@ -629,9 +629,6 @@
{ {
"name": "elementPropertyInternal" "name": "elementPropertyInternal"
}, },
{
"name": "enterView"
},
{ {
"name": "executeCheckHooks" "name": "executeCheckHooks"
}, },
@ -1058,9 +1055,6 @@
{ {
"name": "iterateListLike" "name": "iterateListLike"
}, },
{
"name": "leaveView"
},
{ {
"name": "listenerInternal" "name": "listenerInternal"
}, },
@ -1256,6 +1250,9 @@
{ {
"name": "selectInternal" "name": "selectInternal"
}, },
{
"name": "selectView"
},
{ {
"name": "setActiveHostElement" "name": "setActiveHostElement"
}, },

View File

@ -17,7 +17,7 @@ import {TNODE} from '../../src/render3/interfaces/injector';
import {TNodeType} from '../../src/render3/interfaces/node'; import {TNodeType} from '../../src/render3/interfaces/node';
import {isProceduralRenderer} from '../../src/render3/interfaces/renderer'; import {isProceduralRenderer} from '../../src/render3/interfaces/renderer';
import {LViewFlags, TVIEW} from '../../src/render3/interfaces/view'; import {LViewFlags, TVIEW} from '../../src/render3/interfaces/view';
import {enterView, leaveView} from '../../src/render3/state'; import {selectView} from '../../src/render3/state';
import {ViewRef} from '../../src/render3/view_ref'; import {ViewRef} from '../../src/render3/view_ref';
import {getRendererFactory2} from './imported_renderer2'; import {getRendererFactory2} from './imported_renderer2';
@ -606,7 +606,7 @@ describe('di', () => {
const contentView = createLView( const contentView = createLView(
null, createTView(-1, null, 1, 0, null, null, null, null), null, LViewFlags.CheckAlways, null, createTView(-1, null, 1, 0, null, null, null, null), null, LViewFlags.CheckAlways,
null, null, {} as any, {} as any); null, null, {} as any, {} as any);
const oldView = enterView(contentView, null); const oldView = selectView(contentView, null);
try { try {
const parentTNode = const parentTNode =
getOrCreateTNode(contentView[TVIEW], null, 0, TNodeType.Element, null, null); getOrCreateTNode(contentView[TVIEW], null, 0, TNodeType.Element, null, null);
@ -618,7 +618,7 @@ describe('di', () => {
const injector = getOrCreateNodeInjectorForNode(parentTNode, contentView); const injector = getOrCreateNodeInjectorForNode(parentTNode, contentView);
expect(injector).not.toEqual(-1); expect(injector).not.toEqual(-1);
} finally { } finally {
leaveView(oldView); selectView(oldView, null);
} }
}); });
}); });

View File

@ -14,7 +14,7 @@ import {ViewContainerRef} from '@angular/core/src/linker/view_container_ref';
import {Renderer2} from '@angular/core/src/render/api'; import {Renderer2} from '@angular/core/src/render/api';
import {createLView, createTView, getOrCreateTNode, getOrCreateTView, renderComponentOrTemplate} from '@angular/core/src/render3/instructions/shared'; import {createLView, createTView, getOrCreateTNode, getOrCreateTView, renderComponentOrTemplate} from '@angular/core/src/render3/instructions/shared';
import {TNodeType} from '@angular/core/src/render3/interfaces/node'; import {TNodeType} from '@angular/core/src/render3/interfaces/node';
import {enterView, getLView, resetComponentState} from '@angular/core/src/render3/state'; import {getLView, resetComponentState, selectView} from '@angular/core/src/render3/state';
import {stringifyElement} from '@angular/platform-browser/testing/src/browser_util'; import {stringifyElement} from '@angular/platform-browser/testing/src/browser_util';
import {SWITCH_CHANGE_DETECTOR_REF_FACTORY__POST_R3__ as R3_CHANGE_DETECTOR_REF_FACTORY} from '../../src/change_detection/change_detector_ref'; import {SWITCH_CHANGE_DETECTOR_REF_FACTORY__POST_R3__ as R3_CHANGE_DETECTOR_REF_FACTORY} from '../../src/change_detection/change_detector_ref';
@ -257,7 +257,7 @@ export function renderTemplate<T>(
const hostLView = createLView( const hostLView = createLView(
null, tView, {}, LViewFlags.CheckAlways | LViewFlags.IsRoot, null, null, null, tView, {}, LViewFlags.CheckAlways | LViewFlags.IsRoot, null, null,
providedRendererFactory, renderer); providedRendererFactory, renderer);
enterView(hostLView, null); // SUSPECT! why do we need to enter the View? selectView(hostLView, null); // SUSPECT! why do we need to enter the View?
const def: ComponentDef<any> = ɵɵdefineComponent({ const def: ComponentDef<any> = ɵɵdefineComponent({
factory: () => null, factory: () => null,