refactor(ivy): move LView.template and component templates to TView (#24300)
PR Close #24300
This commit is contained in:
parent
d814eaad95
commit
57eacf4b5a
|
@ -139,7 +139,7 @@ export function renderComponent<T>(
|
||||||
};
|
};
|
||||||
const rootView: LView = createLView(
|
const rootView: LView = createLView(
|
||||||
rendererFactory.createRenderer(hostNode, componentDef.rendererType),
|
rendererFactory.createRenderer(hostNode, componentDef.rendererType),
|
||||||
createTView(-1, null, null), null, rootContext,
|
createTView(-1, null, null, null), rootContext,
|
||||||
componentDef.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways);
|
componentDef.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways);
|
||||||
rootView.injector = opts.injector || null;
|
rootView.injector = opts.injector || null;
|
||||||
|
|
||||||
|
@ -160,7 +160,7 @@ export function renderComponent<T>(
|
||||||
|
|
||||||
executeInitAndContentHooks();
|
executeInitAndContentHooks();
|
||||||
setHostBindings(ROOT_DIRECTIVE_INDICES);
|
setHostBindings(ROOT_DIRECTIVE_INDICES);
|
||||||
detectChangesInternal(elementNode.data as LView, elementNode, componentDef, component);
|
detectChangesInternal(elementNode.data as LView, elementNode, component);
|
||||||
} finally {
|
} finally {
|
||||||
leaveView(oldView);
|
leaveView(oldView);
|
||||||
if (rendererFactory.end) rendererFactory.end();
|
if (rendererFactory.end) rendererFactory.end();
|
||||||
|
|
|
@ -704,12 +704,12 @@ export function getOrCreateTemplateRef<T>(di: LInjector): viewEngine_TemplateRef
|
||||||
const hostTNode = hostNode.tNode;
|
const hostTNode = hostNode.tNode;
|
||||||
const hostTView = hostNode.view.tView;
|
const hostTView = hostNode.view.tView;
|
||||||
if (!hostTNode.tViews) {
|
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');
|
ngDevMode && assertNotNull(hostTNode.tViews, 'TView must be allocated');
|
||||||
di.templateRef = new TemplateRef<any>(
|
di.templateRef = new TemplateRef<any>(
|
||||||
getOrCreateElementRef(di), hostTNode.tViews as TView, hostNode.data.template !,
|
getOrCreateElementRef(di), hostTNode.tViews as TView, getRenderer(), hostNode.data.queries);
|
||||||
getRenderer(), hostNode.data.queries);
|
|
||||||
}
|
}
|
||||||
return di.templateRef;
|
return di.templateRef;
|
||||||
}
|
}
|
||||||
|
@ -718,15 +718,14 @@ class TemplateRef<T> implements viewEngine_TemplateRef<T> {
|
||||||
readonly elementRef: viewEngine_ElementRef;
|
readonly elementRef: viewEngine_ElementRef;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
elementRef: viewEngine_ElementRef, private _tView: TView,
|
elementRef: viewEngine_ElementRef, private _tView: TView, private _renderer: Renderer3,
|
||||||
private _template: ComponentTemplate<T>, private _renderer: Renderer3,
|
|
||||||
private _queries: LQueries|null) {
|
private _queries: LQueries|null) {
|
||||||
this.elementRef = elementRef;
|
this.elementRef = elementRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
createEmbeddedView(context: T): viewEngine_EmbeddedViewRef<T> {
|
createEmbeddedView(context: T): viewEngine_EmbeddedViewRef<T> {
|
||||||
const viewNode = renderEmbeddedTemplate(
|
const viewNode =
|
||||||
null, this._tView, this._template, context, this._renderer, this._queries);
|
renderEmbeddedTemplate(null, this._tView, context, this._renderer, this._queries);
|
||||||
return new EmbeddedViewRef(viewNode, this._template, context);
|
return new EmbeddedViewRef(viewNode, this._tView.template !as ComponentTemplate<T>, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -303,8 +303,8 @@ export function executeInitAndContentHooks(): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createLView<T>(
|
export function createLView<T>(
|
||||||
renderer: Renderer3, tView: TView, template: ComponentTemplate<T>| null, context: T | null,
|
renderer: Renderer3, tView: TView, context: T | null, flags: LViewFlags,
|
||||||
flags: LViewFlags, sanitizer?: Sanitizer | null): LView {
|
sanitizer?: Sanitizer | null): LView {
|
||||||
const newView = {
|
const newView = {
|
||||||
parent: currentView,
|
parent: currentView,
|
||||||
flags: flags | LViewFlags.CreationMode | LViewFlags.Attached | LViewFlags.RunInit,
|
flags: flags | LViewFlags.CreationMode | LViewFlags.Attached | LViewFlags.RunInit,
|
||||||
|
@ -317,7 +317,6 @@ export function createLView<T>(
|
||||||
tail: null,
|
tail: null,
|
||||||
next: null,
|
next: null,
|
||||||
bindingIndex: -1,
|
bindingIndex: -1,
|
||||||
template: template,
|
|
||||||
context: context,
|
context: context,
|
||||||
queries: null,
|
queries: null,
|
||||||
injector: currentView && currentView.injector,
|
injector: currentView && currentView.injector,
|
||||||
|
@ -469,8 +468,8 @@ export function renderTemplate<T>(
|
||||||
host = createLNode(
|
host = createLNode(
|
||||||
-1, TNodeType.Element, hostNode, null, null,
|
-1, TNodeType.Element, hostNode, null, null,
|
||||||
createLView(
|
createLView(
|
||||||
providedRendererFactory.createRenderer(null, null), tView, null, {},
|
providedRendererFactory.createRenderer(null, null), tView, {}, LViewFlags.CheckAlways,
|
||||||
LViewFlags.CheckAlways, sanitizer));
|
sanitizer));
|
||||||
}
|
}
|
||||||
const hostView = host.data !;
|
const hostView = host.data !;
|
||||||
ngDevMode && assertNotNull(hostView, 'Host node should have an LView defined in 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.
|
* TView for dynamically created views on their host TNode, which only has one instance.
|
||||||
*/
|
*/
|
||||||
export function renderEmbeddedTemplate<T>(
|
export function renderEmbeddedTemplate<T>(
|
||||||
viewNode: LViewNode | null, tView: TView, template: ComponentTemplate<T>, context: T,
|
viewNode: LViewNode | null, tView: TView, context: T, renderer: Renderer3,
|
||||||
renderer: Renderer3, queries?: LQueries | null): LViewNode {
|
queries?: LQueries | null): LViewNode {
|
||||||
const _isParent = isParent;
|
const _isParent = isParent;
|
||||||
const _previousOrParentNode = previousOrParentNode;
|
const _previousOrParentNode = previousOrParentNode;
|
||||||
let oldView: LView;
|
let oldView: LView;
|
||||||
|
@ -500,8 +499,8 @@ export function renderEmbeddedTemplate<T>(
|
||||||
previousOrParentNode = null !;
|
previousOrParentNode = null !;
|
||||||
|
|
||||||
if (viewNode == null) {
|
if (viewNode == null) {
|
||||||
const lView = createLView(
|
const lView =
|
||||||
renderer, tView, template, context, LViewFlags.CheckAlways, getCurrentSanitizer());
|
createLView(renderer, tView, context, LViewFlags.CheckAlways, getCurrentSanitizer());
|
||||||
|
|
||||||
if (queries) {
|
if (queries) {
|
||||||
lView.queries = queries.createView();
|
lView.queries = queries.createView();
|
||||||
|
@ -511,7 +510,7 @@ export function renderEmbeddedTemplate<T>(
|
||||||
rf = RenderFlags.Create;
|
rf = RenderFlags.Create;
|
||||||
}
|
}
|
||||||
oldView = enterView(viewNode.data, viewNode);
|
oldView = enterView(viewNode.data, viewNode);
|
||||||
template(rf, context);
|
tView.template !(rf, context);
|
||||||
if (rf & RenderFlags.Update) {
|
if (rf & RenderFlags.Update) {
|
||||||
refreshView();
|
refreshView();
|
||||||
} else {
|
} else {
|
||||||
|
@ -788,7 +787,7 @@ function getOrCreateTView(
|
||||||
// and not on embedded templates.
|
// and not on embedded templates.
|
||||||
|
|
||||||
return template.ngPrivateData ||
|
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
|
* @param pipes Registry of pipes for this view
|
||||||
*/
|
*/
|
||||||
export function createTView(
|
export function createTView(
|
||||||
viewIndex: number, directives: DirectiveDefListOrFactory | null,
|
viewIndex: number, template: ComponentTemplate<any>| null,
|
||||||
pipes: PipeDefListOrFactory | null): TView {
|
directives: DirectiveDefListOrFactory | null, pipes: PipeDefListOrFactory | null): TView {
|
||||||
ngDevMode && ngDevMode.tView++;
|
ngDevMode && ngDevMode.tView++;
|
||||||
return {
|
return {
|
||||||
id: viewIndex,
|
id: viewIndex,
|
||||||
|
template: template,
|
||||||
node: null !,
|
node: null !,
|
||||||
data: [],
|
data: [],
|
||||||
childIndex: -1, // Children set in addToViewTree(), if any
|
childIndex: -1, // Children set in addToViewTree(), if any
|
||||||
|
@ -887,7 +887,7 @@ export function hostElement(
|
||||||
const node = createLNode(
|
const node = createLNode(
|
||||||
0, TNodeType.Element, rNode, null, null,
|
0, TNodeType.Element, rNode, null, null,
|
||||||
createLView(
|
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));
|
def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways, sanitizer));
|
||||||
|
|
||||||
if (firstTemplatePass) {
|
if (firstTemplatePass) {
|
||||||
|
@ -1337,7 +1337,7 @@ function addComponentLogic<T>(index: number, instance: T, def: ComponentDef<T>):
|
||||||
currentView, previousOrParentNode.tNode.index as number,
|
currentView, previousOrParentNode.tNode.index as number,
|
||||||
createLView(
|
createLView(
|
||||||
rendererFactory.createRenderer(previousOrParentNode.native as RElement, def.rendererType),
|
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()));
|
getCurrentSanitizer()));
|
||||||
|
|
||||||
// We need to set the host node/data here because when the component LNode was created,
|
// 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.
|
// The directives and pipes are not needed here as an existing view is only being refreshed.
|
||||||
const dynamicView = lViewNode.data;
|
const dynamicView = lViewNode.data;
|
||||||
ngDevMode && assertNotNull(dynamicView.tView, 'TView must be allocated');
|
ngDevMode && assertNotNull(dynamicView.tView, 'TView must be allocated');
|
||||||
renderEmbeddedTemplate(
|
renderEmbeddedTemplate(lViewNode, dynamicView.tView, dynamicView.context !, renderer);
|
||||||
lViewNode, dynamicView.tView, dynamicView.template !, dynamicView.context !, renderer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1653,8 +1652,8 @@ export function embeddedViewStart(viewBlockId: number): RenderFlags {
|
||||||
} 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.
|
||||||
const newView = createLView(
|
const newView = createLView(
|
||||||
renderer, getOrCreateEmbeddedTView(viewBlockId, container), null, null,
|
renderer, getOrCreateEmbeddedTView(viewBlockId, container), null, LViewFlags.CheckAlways,
|
||||||
LViewFlags.CheckAlways, getCurrentSanitizer());
|
getCurrentSanitizer());
|
||||||
|
|
||||||
if (lContainer.queries) {
|
if (lContainer.queries) {
|
||||||
newView.queries = lContainer.queries.createView();
|
newView.queries = lContainer.queries.createView();
|
||||||
|
@ -1685,7 +1684,7 @@ function getOrCreateEmbeddedTView(viewIndex: number, parent: LContainerNode): TV
|
||||||
if (viewIndex >= containerTViews.length || containerTViews[viewIndex] == null) {
|
if (viewIndex >= containerTViews.length || containerTViews[viewIndex] == null) {
|
||||||
const tView = currentView.tView;
|
const tView = currentView.tView;
|
||||||
containerTViews[viewIndex] =
|
containerTViews[viewIndex] =
|
||||||
createTView(viewIndex, tView.directiveRegistry, tView.pipeRegistry);
|
createTView(viewIndex, null, tView.directiveRegistry, tView.pipeRegistry);
|
||||||
}
|
}
|
||||||
return containerTViews[viewIndex];
|
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
|
// Only attached CheckAlways components or attached, dirty OnPush components should be checked
|
||||||
if (viewAttached(hostView) && hostView.flags & (LViewFlags.CheckAlways | LViewFlags.Dirty)) {
|
if (viewAttached(hostView) && hostView.flags & (LViewFlags.CheckAlways | LViewFlags.Dirty)) {
|
||||||
ngDevMode && assertDataInRange(directiveIndex, directives !);
|
ngDevMode && assertDataInRange(directiveIndex, directives !);
|
||||||
const def = currentView.tView.directives ![directiveIndex] as ComponentDef<T>;
|
detectChangesInternal(hostView, element, getDirectiveInstance(directives ![directiveIndex]));
|
||||||
|
|
||||||
detectChangesInternal(
|
|
||||||
hostView, element, def, getDirectiveInstance(directives ![directiveIndex]));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2078,9 +2074,7 @@ export function getRootView(component: any): LView {
|
||||||
export function detectChanges<T>(component: T): void {
|
export function detectChanges<T>(component: T): void {
|
||||||
const hostNode = _getComponentHostLElementNode(component);
|
const hostNode = _getComponentHostLElementNode(component);
|
||||||
ngDevMode && assertNotNull(hostNode.data, 'Component host node should be attached to an LView');
|
ngDevMode && assertNotNull(hostNode.data, 'Component host node should be attached to an LView');
|
||||||
const componentIndex = hostNode.tNode.flags >> TNodeFlags.DirectiveStartingIndexShift;
|
detectChangesInternal(hostNode.data as LView, hostNode, component);
|
||||||
const def = hostNode.view.tView.directives ![componentIndex] as ComponentDef<T>;
|
|
||||||
detectChangesInternal(hostNode.data as LView, hostNode, def, 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. */
|
/** Checks the view of the component provided. Does not gate on dirty checks or execute doCheck. */
|
||||||
export function detectChangesInternal<T>(
|
export function detectChangesInternal<T>(hostView: LView, hostNode: LElementNode, component: T) {
|
||||||
hostView: LView, hostNode: LElementNode, def: ComponentDef<T>, component: T) {
|
|
||||||
const oldView = enterView(hostView, hostNode);
|
const oldView = enterView(hostView, hostNode);
|
||||||
const template = def.template;
|
const template = hostView.tView.template !;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
template(getRenderFlags(hostView), component);
|
template(getRenderFlags(hostView), component);
|
||||||
|
|
|
@ -126,11 +126,6 @@ export interface LView {
|
||||||
*/
|
*/
|
||||||
tView: TView;
|
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 embedded views, the context with which to render the template.
|
||||||
* - For root view of the root component the context contains change detection data.
|
* - For root view of the root component the context contains change detection data.
|
||||||
|
@ -212,6 +207,12 @@ export interface TView {
|
||||||
*/
|
*/
|
||||||
readonly id: number;
|
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.
|
* Pointer to the `TNode` that represents the root of the view.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1404,7 +1404,7 @@ describe('di', () => {
|
||||||
describe('getOrCreateNodeInjector', () => {
|
describe('getOrCreateNodeInjector', () => {
|
||||||
it('should handle initial undefined state', () => {
|
it('should handle initial undefined state', () => {
|
||||||
const contentView =
|
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 !);
|
const oldView = enterView(contentView, null !);
|
||||||
try {
|
try {
|
||||||
const parent = createLNode(0, TNodeType.Element, null, null, null, null);
|
const parent = createLNode(0, TNodeType.Element, null, null, null, null);
|
||||||
|
|
Loading…
Reference in New Issue