perf(ivy): remove firstTemplatePass check for component view creation (#31946)

PR Close #31946
This commit is contained in:
Pawel Kozlowski 2019-08-01 14:00:23 +02:00 committed by Alex Rickabaugh
parent f2d47c96c4
commit a7c71d1a57
6 changed files with 33 additions and 37 deletions

View File

@ -70,6 +70,7 @@ export function assertLView(value: any) {
assertEqual(isLView(value), true, 'Expecting LView');
}
export function assertFirstTemplatePass(tView: TView, errMessage: string) {
assertEqual(tView.firstTemplatePass, true, errMessage);
export function assertFirstTemplatePass(tView: TView, errMessage?: string) {
assertEqual(
tView.firstTemplatePass, true, errMessage || 'Should only be called in first template pass.');
}

View File

@ -17,9 +17,9 @@ import {assertComponentType} from './assert';
import {getComponentDef} from './definition';
import {diPublicInInjector, getOrCreateNodeInjectorForNode} from './di';
import {registerPostOrderHooks, registerPreOrderHooks} from './hooks';
import {CLEAN_PROMISE, addToViewTree, createLView, createTView, getOrCreateTNode, getOrCreateTView, initNodeFlags, instantiateRootComponent, invokeHostBindingsInCreationMode, locateHostElement, queueComponentIndexForCheck, refreshDescendantViews} from './instructions/shared';
import {CLEAN_PROMISE, addToViewTree, createLView, createTView, getOrCreateTNode, getOrCreateTView, initNodeFlags, instantiateRootComponent, invokeHostBindingsInCreationMode, locateHostElement, markAsComponentHost, refreshDescendantViews} from './instructions/shared';
import {ComponentDef, ComponentType, RenderFlags} from './interfaces/definition';
import {TElementNode, TNode, TNodeFlags, TNodeType} from './interfaces/node';
import {TElementNode, TNode, TNodeType} from './interfaces/node';
import {PlayerHandler} from './interfaces/player';
import {RElement, Renderer3, RendererFactory3, domRendererFactory3} from './interfaces/renderer';
import {CONTEXT, FLAGS, HEADER_OFFSET, LView, LViewFlags, RootContext, RootContextFlags, TVIEW} from './interfaces/view';
@ -184,9 +184,8 @@ export function createRootComponentView(
if (tView.firstTemplatePass) {
diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, rootView), tView, def.type);
tNode.flags = TNodeFlags.isComponent;
markAsComponentHost(tView, tNode);
initNodeFlags(tNode, rootView.length, 1);
queueComponentIndexForCheck(tNode);
}
// Store component view at node index, with node as the HOST

View File

@ -14,7 +14,7 @@ import {Sanitizer} from '../../sanitization/security';
import {assertDataInRange, assertDefined, assertDomNode, assertEqual, assertGreaterThan, assertNotEqual, assertNotSame} from '../../util/assert';
import {createNamedArrayType} from '../../util/named_array_type';
import {normalizeDebugBindingName, normalizeDebugBindingValue} from '../../util/ng_reflect';
import {assertLView, assertPreviousIsParent} from '../assert';
import {assertFirstTemplatePass, assertLView, assertPreviousIsParent} from '../assert';
import {attachPatchData, getComponentViewByInstance} from '../context_discovery';
import {diPublicInInjector, getNodeInjectable, getOrCreateNodeInjectorForNode} from '../di';
import {throwMultipleComponentError} from '../errors';
@ -1207,7 +1207,7 @@ function postProcessBaseDirective<T>(
function findDirectiveMatches(
tView: TView, viewData: LView,
tNode: TElementNode | TContainerNode | TElementContainerNode): DirectiveDef<any>[]|null {
ngDevMode && assertEqual(tView.firstTemplatePass, true, 'should run on first template pass only');
ngDevMode && assertFirstTemplatePass(tView);
const registry = tView.directiveRegistry;
let matches: any[]|null = null;
if (registry) {
@ -1219,8 +1219,7 @@ function findDirectiveMatches(
if (isComponentDef(def)) {
if (tNode.flags & TNodeFlags.isComponent) throwMultipleComponentError(tNode);
tNode.flags = TNodeFlags.isComponent;
markAsComponentHost(tView, tNode);
// The component is always stored first with directives after.
matches.unshift(def);
} else {
@ -1232,13 +1231,16 @@ function findDirectiveMatches(
return matches;
}
/** Stores index of component's host element so it will be queued for view refresh during CD. */
export function queueComponentIndexForCheck(previousOrParentTNode: TNode): void {
const tView = getLView()[TVIEW];
ngDevMode &&
assertEqual(tView.firstTemplatePass, true, 'Should only be called in first template pass.');
/**
* Marks a given TNode as a component's host. This consists of:
* - setting appropriate TNode flags;
* - storing index of component's host element so it will be queued for view refresh during CD.
*/
export function markAsComponentHost(tView: TView, hostTNode: TNode): void {
ngDevMode && assertFirstTemplatePass(tView);
hostTNode.flags = TNodeFlags.isComponent;
(tView.components || (tView.components = ngDevMode ? new TViewComponents !() : [
])).push(previousOrParentTNode.index);
])).push(hostTNode.index);
}
@ -1306,10 +1308,8 @@ function baseResolveDirective<T>(
viewData.push(nodeInjectorFactory);
}
function addComponentLogic<T>(
lView: LView, previousOrParentTNode: TNode, def: ComponentDef<T>): void {
const native = getNativeByTNode(previousOrParentTNode, lView);
function addComponentLogic<T>(lView: LView, hostTNode: TNode, def: ComponentDef<T>): void {
const native = getNativeByTNode(hostTNode, lView);
const tView = getOrCreateTView(def);
// Only component views should be added to the view tree directly. Embedded views are
@ -1318,18 +1318,14 @@ function addComponentLogic<T>(
const componentView = addToViewTree(
lView, createLView(
lView, tView, null, def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways,
lView[previousOrParentTNode.index], previousOrParentTNode as TElementNode,
rendererFactory, rendererFactory.createRenderer(native as RElement, def)));
lView[hostTNode.index], hostTNode as TElementNode, rendererFactory,
rendererFactory.createRenderer(native as RElement, def)));
componentView[T_HOST] = previousOrParentTNode as TElementNode;
componentView[T_HOST] = hostTNode as TElementNode;
// Component view will always be created before any injected LContainers,
// so this is a regular element, wrap it with the component view
lView[previousOrParentTNode.index] = componentView;
if (lView[TVIEW].firstTemplatePass) {
queueComponentIndexForCheck(previousOrParentTNode);
}
lView[hostTNode.index] = componentView;
}
export function elementAttributeInternal(

View File

@ -515,6 +515,9 @@
{
"name": "locateHostElement"
},
{
"name": "markAsComponentHost"
},
{
"name": "matchTemplateAttribute"
},
@ -545,9 +548,6 @@
{
"name": "postProcessDirective"
},
{
"name": "queueComponentIndexForCheck"
},
{
"name": "readPatchedData"
},

View File

@ -386,6 +386,9 @@
{
"name": "locateHostElement"
},
{
"name": "markAsComponentHost"
},
{
"name": "namespaceHTMLInternal"
},
@ -410,9 +413,6 @@
{
"name": "postProcessBaseDirective"
},
{
"name": "queueComponentIndexForCheck"
},
{
"name": "readPatchedData"
},

View File

@ -1118,6 +1118,9 @@
{
"name": "makeParamDecorator"
},
{
"name": "markAsComponentHost"
},
{
"name": "markContextToPersistState"
},
@ -1178,9 +1181,6 @@
{
"name": "postProcessDirective"
},
{
"name": "queueComponentIndexForCheck"
},
{
"name": "readPatchedData"
},