refactor(ivy): move LView.template and component templates to TView (#24300)

PR Close #24300
This commit is contained in:
Kara Erickson 2018-06-04 13:07:09 -07:00 committed by Victor Berchet
parent d814eaad95
commit 57eacf4b5a
5 changed files with 39 additions and 46 deletions

View File

@ -139,7 +139,7 @@ export function renderComponent<T>(
};
const rootView: LView = createLView(
rendererFactory.createRenderer(hostNode, componentDef.rendererType),
createTView(-1, null, null), null, rootContext,
createTView(-1, null, null, null), rootContext,
componentDef.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways);
rootView.injector = opts.injector || null;
@ -160,7 +160,7 @@ export function renderComponent<T>(
executeInitAndContentHooks();
setHostBindings(ROOT_DIRECTIVE_INDICES);
detectChangesInternal(elementNode.data as LView, elementNode, componentDef, component);
detectChangesInternal(elementNode.data as LView, elementNode, component);
} finally {
leaveView(oldView);
if (rendererFactory.end) rendererFactory.end();

View File

@ -704,12 +704,12 @@ export function getOrCreateTemplateRef<T>(di: LInjector): viewEngine_TemplateRef
const hostTNode = hostNode.tNode;
const hostTView = hostNode.view.tView;
if (!hostTNode.tViews) {
hostTNode.tViews = createTView(-1, hostTView.directiveRegistry, hostTView.pipeRegistry);
hostTNode.tViews = createTView(
-1, hostNode.data.template !, hostTView.directiveRegistry, hostTView.pipeRegistry);
}
ngDevMode && assertNotNull(hostTNode.tViews, 'TView must be allocated');
di.templateRef = new TemplateRef<any>(
getOrCreateElementRef(di), hostTNode.tViews as TView, hostNode.data.template !,
getRenderer(), hostNode.data.queries);
getOrCreateElementRef(di), hostTNode.tViews as TView, getRenderer(), hostNode.data.queries);
}
return di.templateRef;
}
@ -718,15 +718,14 @@ class TemplateRef<T> implements viewEngine_TemplateRef<T> {
readonly elementRef: viewEngine_ElementRef;
constructor(
elementRef: viewEngine_ElementRef, private _tView: TView,
private _template: ComponentTemplate<T>, private _renderer: Renderer3,
elementRef: viewEngine_ElementRef, private _tView: TView, private _renderer: Renderer3,
private _queries: LQueries|null) {
this.elementRef = elementRef;
}
createEmbeddedView(context: T): viewEngine_EmbeddedViewRef<T> {
const viewNode = renderEmbeddedTemplate(
null, this._tView, this._template, context, this._renderer, this._queries);
return new EmbeddedViewRef(viewNode, this._template, context);
const viewNode =
renderEmbeddedTemplate(null, this._tView, context, this._renderer, this._queries);
return new EmbeddedViewRef(viewNode, this._tView.template !as ComponentTemplate<T>, context);
}
}

View File

@ -303,8 +303,8 @@ export function executeInitAndContentHooks(): void {
}
export function createLView<T>(
renderer: Renderer3, tView: TView, template: ComponentTemplate<T>| null, context: T | null,
flags: LViewFlags, sanitizer?: Sanitizer | null): LView {
renderer: Renderer3, tView: TView, context: T | null, flags: LViewFlags,
sanitizer?: Sanitizer | null): LView {
const newView = {
parent: currentView,
flags: flags | LViewFlags.CreationMode | LViewFlags.Attached | LViewFlags.RunInit,
@ -317,7 +317,6 @@ export function createLView<T>(
tail: null,
next: null,
bindingIndex: -1,
template: template,
context: context,
queries: null,
injector: currentView && currentView.injector,
@ -469,8 +468,8 @@ export function renderTemplate<T>(
host = createLNode(
-1, TNodeType.Element, hostNode, null, null,
createLView(
providedRendererFactory.createRenderer(null, null), tView, null, {},
LViewFlags.CheckAlways, sanitizer));
providedRendererFactory.createRenderer(null, null), tView, {}, LViewFlags.CheckAlways,
sanitizer));
}
const hostView = host.data !;
ngDevMode && assertNotNull(hostView, 'Host node should have an LView defined in host.data.');
@ -489,8 +488,8 @@ export function renderTemplate<T>(
* TView for dynamically created views on their host TNode, which only has one instance.
*/
export function renderEmbeddedTemplate<T>(
viewNode: LViewNode | null, tView: TView, template: ComponentTemplate<T>, context: T,
renderer: Renderer3, queries?: LQueries | null): LViewNode {
viewNode: LViewNode | null, tView: TView, context: T, renderer: Renderer3,
queries?: LQueries | null): LViewNode {
const _isParent = isParent;
const _previousOrParentNode = previousOrParentNode;
let oldView: LView;
@ -500,8 +499,8 @@ export function renderEmbeddedTemplate<T>(
previousOrParentNode = null !;
if (viewNode == null) {
const lView = createLView(
renderer, tView, template, context, LViewFlags.CheckAlways, getCurrentSanitizer());
const lView =
createLView(renderer, tView, context, LViewFlags.CheckAlways, getCurrentSanitizer());
if (queries) {
lView.queries = queries.createView();
@ -511,7 +510,7 @@ export function renderEmbeddedTemplate<T>(
rf = RenderFlags.Create;
}
oldView = enterView(viewNode.data, viewNode);
template(rf, context);
tView.template !(rf, context);
if (rf & RenderFlags.Update) {
refreshView();
} else {
@ -788,7 +787,7 @@ function getOrCreateTView(
// and not on embedded templates.
return template.ngPrivateData ||
(template.ngPrivateData = createTView(-1, directives, pipes) as never);
(template.ngPrivateData = createTView(-1, template, directives, pipes) as never);
}
/**
@ -799,11 +798,12 @@ function getOrCreateTView(
* @param pipes Registry of pipes for this view
*/
export function createTView(
viewIndex: number, directives: DirectiveDefListOrFactory | null,
pipes: PipeDefListOrFactory | null): TView {
viewIndex: number, template: ComponentTemplate<any>| null,
directives: DirectiveDefListOrFactory | null, pipes: PipeDefListOrFactory | null): TView {
ngDevMode && ngDevMode.tView++;
return {
id: viewIndex,
template: template,
node: null !,
data: [],
childIndex: -1, // Children set in addToViewTree(), if any
@ -887,7 +887,7 @@ export function hostElement(
const node = createLNode(
0, TNodeType.Element, rNode, null, null,
createLView(
renderer, getOrCreateTView(def.template, def.directiveDefs, def.pipeDefs), null, null,
renderer, getOrCreateTView(def.template, def.directiveDefs, def.pipeDefs), null,
def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways, sanitizer));
if (firstTemplatePass) {
@ -1337,7 +1337,7 @@ function addComponentLogic<T>(index: number, instance: T, def: ComponentDef<T>):
currentView, previousOrParentNode.tNode.index as number,
createLView(
rendererFactory.createRenderer(previousOrParentNode.native as RElement, def.rendererType),
tView, null, null, def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways,
tView, null, def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways,
getCurrentSanitizer()));
// We need to set the host node/data here because when the component LNode was created,
@ -1592,8 +1592,7 @@ function refreshDynamicChildren() {
// The directives and pipes are not needed here as an existing view is only being refreshed.
const dynamicView = lViewNode.data;
ngDevMode && assertNotNull(dynamicView.tView, 'TView must be allocated');
renderEmbeddedTemplate(
lViewNode, dynamicView.tView, dynamicView.template !, dynamicView.context !, renderer);
renderEmbeddedTemplate(lViewNode, dynamicView.tView, dynamicView.context !, renderer);
}
}
}
@ -1653,8 +1652,8 @@ export function embeddedViewStart(viewBlockId: number): RenderFlags {
} else {
// When we create a new LView, we always reset the state of the instructions.
const newView = createLView(
renderer, getOrCreateEmbeddedTView(viewBlockId, container), null, null,
LViewFlags.CheckAlways, getCurrentSanitizer());
renderer, getOrCreateEmbeddedTView(viewBlockId, container), null, LViewFlags.CheckAlways,
getCurrentSanitizer());
if (lContainer.queries) {
newView.queries = lContainer.queries.createView();
@ -1685,7 +1684,7 @@ function getOrCreateEmbeddedTView(viewIndex: number, parent: LContainerNode): TV
if (viewIndex >= containerTViews.length || containerTViews[viewIndex] == null) {
const tView = currentView.tView;
containerTViews[viewIndex] =
createTView(viewIndex, tView.directiveRegistry, tView.pipeRegistry);
createTView(viewIndex, null, tView.directiveRegistry, tView.pipeRegistry);
}
return containerTViews[viewIndex];
}
@ -1760,10 +1759,7 @@ export function componentRefresh<T>(directiveIndex: number, elementIndex: number
// Only attached CheckAlways components or attached, dirty OnPush components should be checked
if (viewAttached(hostView) && hostView.flags & (LViewFlags.CheckAlways | LViewFlags.Dirty)) {
ngDevMode && assertDataInRange(directiveIndex, directives !);
const def = currentView.tView.directives ![directiveIndex] as ComponentDef<T>;
detectChangesInternal(
hostView, element, def, getDirectiveInstance(directives ![directiveIndex]));
detectChangesInternal(hostView, element, getDirectiveInstance(directives ![directiveIndex]));
}
}
@ -2078,9 +2074,7 @@ export function getRootView(component: any): LView {
export function detectChanges<T>(component: T): void {
const hostNode = _getComponentHostLElementNode(component);
ngDevMode && assertNotNull(hostNode.data, 'Component host node should be attached to an LView');
const componentIndex = hostNode.tNode.flags >> TNodeFlags.DirectiveStartingIndexShift;
const def = hostNode.view.tView.directives ![componentIndex] as ComponentDef<T>;
detectChangesInternal(hostNode.data as LView, hostNode, def, component);
detectChangesInternal(hostNode.data as LView, hostNode, component);
}
@ -2100,10 +2094,9 @@ export function checkNoChanges<T>(component: T): void {
}
/** Checks the view of the component provided. Does not gate on dirty checks or execute doCheck. */
export function detectChangesInternal<T>(
hostView: LView, hostNode: LElementNode, def: ComponentDef<T>, component: T) {
export function detectChangesInternal<T>(hostView: LView, hostNode: LElementNode, component: T) {
const oldView = enterView(hostView, hostNode);
const template = def.template;
const template = hostView.tView.template !;
try {
template(getRenderFlags(hostView), component);

View File

@ -126,11 +126,6 @@ export interface LView {
*/
tView: TView;
/**
* For dynamically inserted views, the template function to refresh the view.
*/
template: ComponentTemplate<{}>|null;
/**
* - For embedded views, the context with which to render the template.
* - For root view of the root component the context contains change detection data.
@ -212,6 +207,12 @@ export interface TView {
*/
readonly id: number;
/**
* The template function used to refresh the view of dynamically created views
* and components. Will be null for inline views.
*/
template: ComponentTemplate<{}>|null;
/**
* Pointer to the `TNode` that represents the root of the view.
*

View File

@ -1404,7 +1404,7 @@ describe('di', () => {
describe('getOrCreateNodeInjector', () => {
it('should handle initial undefined state', () => {
const contentView =
createLView(null !, createTView(-1, null, null), null, null, LViewFlags.CheckAlways);
createLView(null !, createTView(-1, null, null, null), null, LViewFlags.CheckAlways);
const oldView = enterView(contentView, null !);
try {
const parent = createLNode(0, TNodeType.Element, null, null, null, null);