perf(ivy): guard directive-related operations with a TNode flag (#32445)

PR Close #32445
This commit is contained in:
Pawel Kozlowski 2019-09-02 15:17:44 +02:00 committed by Miško Hevery
parent a383a5a165
commit 641c5c1c1e
16 changed files with 87 additions and 57 deletions

View File

@ -10,7 +10,7 @@ import {Injector} from '../di';
import {getViewComponent} from '../render3/global_utils_api'; import {getViewComponent} from '../render3/global_utils_api';
import {CONTAINER_HEADER_OFFSET, LContainer, NATIVE} from '../render3/interfaces/container'; import {CONTAINER_HEADER_OFFSET, LContainer, NATIVE} from '../render3/interfaces/container';
import {TElementNode, TNode, TNodeFlags, TNodeType} from '../render3/interfaces/node'; import {TElementNode, TNode, TNodeFlags, TNodeType} from '../render3/interfaces/node';
import {isComponent, isLContainer} from '../render3/interfaces/type_checks'; import {isComponentHost, isLContainer} from '../render3/interfaces/type_checks';
import {LView, PARENT, TData, TVIEW, T_HOST} from '../render3/interfaces/view'; import {LView, PARENT, TData, TVIEW, T_HOST} from '../render3/interfaces/view';
import {TStylingContext} from '../render3/styling_next/interfaces'; import {TStylingContext} from '../render3/styling_next/interfaces';
import {stylingMapToStringMap} from '../render3/styling_next/map_based_bindings'; import {stylingMapToStringMap} from '../render3/styling_next/map_based_bindings';
@ -481,7 +481,7 @@ function _queryNodeChildrenR3(
// Case 1: the TNode is an element // Case 1: the TNode is an element
// The native node has to be checked. // The native node has to be checked.
_addQueryMatchR3(nativeNode, predicate, matches, elementsOnly, rootNativeNode); _addQueryMatchR3(nativeNode, predicate, matches, elementsOnly, rootNativeNode);
if (isComponent(tNode)) { if (isComponentHost(tNode)) {
// If the element is the host of a component, then all nodes in its view have to be processed. // If the element is the host of a component, then all nodes in its view have to be processed.
// Note: the component's content (tNode.child) will be processed from the insertion points. // Note: the component's content (tNode.child) will be processed from the insertion points.
const componentView = getComponentViewByIndex(tNode.index, lView); const componentView = getComponentViewByIndex(tNode.index, lView);

View File

@ -282,14 +282,14 @@ export function getDirectivesAtNodeIndex(
let directiveStartIndex = tNode.directiveStart; let directiveStartIndex = tNode.directiveStart;
if (directiveStartIndex == 0) return EMPTY_ARRAY; if (directiveStartIndex == 0) return EMPTY_ARRAY;
const directiveEndIndex = tNode.directiveEnd; const directiveEndIndex = tNode.directiveEnd;
if (!includeComponents && tNode.flags & TNodeFlags.isComponent) directiveStartIndex++; if (!includeComponents && tNode.flags & TNodeFlags.isComponentHost) directiveStartIndex++;
return lView.slice(directiveStartIndex, directiveEndIndex); return lView.slice(directiveStartIndex, directiveEndIndex);
} }
export function getComponentAtNodeIndex(nodeIndex: number, lView: LView): {}|null { export function getComponentAtNodeIndex(nodeIndex: number, lView: LView): {}|null {
const tNode = lView[TVIEW].data[nodeIndex] as TNode; const tNode = lView[TVIEW].data[nodeIndex] as TNode;
let directiveStartIndex = tNode.directiveStart; let directiveStartIndex = tNode.directiveStart;
return tNode.flags & TNodeFlags.isComponent ? lView[directiveStartIndex] : null; return tNode.flags & TNodeFlags.isComponentHost ? lView[directiveStartIndex] : null;
} }
/** /**

View File

@ -20,7 +20,7 @@ import {NG_ELEMENT_ID} from './fields';
import {DirectiveDef, FactoryFn} from './interfaces/definition'; import {DirectiveDef, FactoryFn} from './interfaces/definition';
import {NO_PARENT_INJECTOR, NodeInjectorFactory, PARENT_INJECTOR, RelativeInjectorLocation, RelativeInjectorLocationFlags, TNODE, isFactory} from './interfaces/injector'; import {NO_PARENT_INJECTOR, NodeInjectorFactory, PARENT_INJECTOR, RelativeInjectorLocation, RelativeInjectorLocationFlags, TNODE, isFactory} from './interfaces/injector';
import {AttributeMarker, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeProviderIndexes, TNodeType} from './interfaces/node'; import {AttributeMarker, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeProviderIndexes, TNodeType} from './interfaces/node';
import {isComponent, isComponentDef} from './interfaces/type_checks'; import {isComponentDef, isComponentHost} from './interfaces/type_checks';
import {DECLARATION_VIEW, INJECTOR, LView, TData, TVIEW, TView, T_HOST} from './interfaces/view'; import {DECLARATION_VIEW, INJECTOR, LView, TData, TVIEW, TView, T_HOST} from './interfaces/view';
import {assertNodeOfPossibleTypes} from './node_assert'; import {assertNodeOfPossibleTypes} from './node_assert';
import {getLView, getPreviousOrParentTNode, setTNodeAndViewData} from './state'; import {getLView, getPreviousOrParentTNode, setTNodeAndViewData} from './state';
@ -154,7 +154,7 @@ export function getOrCreateNodeInjectorForNode(
insertBloom(tView.blueprint, null); insertBloom(tView.blueprint, null);
ngDevMode && assertEqual( ngDevMode && assertEqual(
tNode.flags === 0 || tNode.flags === TNodeFlags.isComponent, true, tNode.flags === 0 || tNode.flags === TNodeFlags.isComponentHost, true,
'expected tNode.flags to not be initialized'); 'expected tNode.flags to not be initialized');
} }
@ -464,7 +464,7 @@ function searchTokensOnInjector<T>(
// - AND the injector set `includeViewProviders` to true (implying that the token can see // - AND the injector set `includeViewProviders` to true (implying that the token can see
// ViewProviders because it is the Component or a Service which itself was declared in // ViewProviders because it is the Component or a Service which itself was declared in
// ViewProviders) // ViewProviders)
(isComponent(tNode) && includeViewProviders) : (isComponentHost(tNode) && includeViewProviders) :
// 2) `previousTView != null` which means that we are now walking across the parent nodes. // 2) `previousTView != null` which means that we are now walking across the parent nodes.
// In such a case we are only allowed to look into the ViewProviders if: // In such a case we are only allowed to look into the ViewProviders if:
// - We just crossed from child View to Parent View `previousTView != currentTView` // - We just crossed from child View to Parent View `previousTView != currentTView`

View File

@ -11,14 +11,15 @@ import {attachPatchData} from '../context_discovery';
import {executeCheckHooks, executeInitAndCheckHooks, incrementInitPhaseFlags, registerPostOrderHooks} from '../hooks'; import {executeCheckHooks, executeInitAndCheckHooks, incrementInitPhaseFlags, registerPostOrderHooks} from '../hooks';
import {ACTIVE_INDEX, CONTAINER_HEADER_OFFSET, LContainer} from '../interfaces/container'; import {ACTIVE_INDEX, CONTAINER_HEADER_OFFSET, LContainer} from '../interfaces/container';
import {ComponentTemplate} from '../interfaces/definition'; import {ComponentTemplate} from '../interfaces/definition';
import {LocalRefExtractor, TAttributes, TContainerNode, TNode, TNodeType, TViewNode} from '../interfaces/node'; import {LocalRefExtractor, TAttributes, TContainerNode, TNode, TNodeFlags, TNodeType, TViewNode} from '../interfaces/node';
import {isDirectiveHost} from '../interfaces/type_checks';
import {BINDING_INDEX, FLAGS, HEADER_OFFSET, InitPhaseState, LView, LViewFlags, RENDERER, TVIEW, T_HOST} from '../interfaces/view'; import {BINDING_INDEX, FLAGS, HEADER_OFFSET, InitPhaseState, LView, LViewFlags, RENDERER, TVIEW, T_HOST} from '../interfaces/view';
import {assertNodeType} from '../node_assert'; import {assertNodeType} from '../node_assert';
import {appendChild, removeView} from '../node_manipulation'; import {appendChild, removeView} from '../node_manipulation';
import {getCheckNoChangesMode, getIsParent, getLView, getPreviousOrParentTNode, setIsNotParent, setPreviousOrParentTNode} from '../state'; import {getCheckNoChangesMode, getIsParent, getLView, getPreviousOrParentTNode, setIsNotParent, setPreviousOrParentTNode} from '../state';
import {getNativeByTNode, load} from '../util/view_utils'; import {getNativeByTNode, load} from '../util/view_utils';
import {addToViewTree, createDirectivesAndLocals, createLContainer, createTNode, createTView, getOrCreateTNode, resolveDirectives} from './shared'; import {addToViewTree, createDirectivesInstances, createLContainer, createTNode, createTView, getOrCreateTNode, resolveDirectives, saveResolvedLocalsInData} from './shared';
@ -89,8 +90,13 @@ export function ɵɵtemplate(
} }
} }
createDirectivesAndLocals(tView, lView, tContainerNode, localRefExtractor); if (isDirectiveHost(tContainerNode)) {
attachPatchData(getNativeByTNode(tContainerNode, lView), lView); createDirectivesInstances(tView, lView, tContainerNode);
}
if (localRefs != null) {
saveResolvedLocalsInData(lView, tContainerNode, localRefExtractor);
}
setIsNotParent(); setIsNotParent();
} }
@ -176,6 +182,7 @@ function containerInternal(
const lContainer = lView[adjustedIndex] = createLContainer(comment, lView, comment, tNode); const lContainer = lView[adjustedIndex] = createLContainer(comment, lView, comment, tNode);
appendChild(comment, tNode, lView); appendChild(comment, tNode, lView);
attachPatchData(getNativeByTNode(tNode, lView), lView);
// Containers are added to the current view tree instead of their embedded views // Containers are added to the current view tree instead of their embedded views
// because views can be removed and re-inserted. // because views can be removed and re-inserted.

View File

@ -12,7 +12,7 @@ import {attachPatchData} from '../context_discovery';
import {registerPostOrderHooks} from '../hooks'; import {registerPostOrderHooks} from '../hooks';
import {TAttributes, TNodeFlags, TNodeType} from '../interfaces/node'; import {TAttributes, TNodeFlags, TNodeType} from '../interfaces/node';
import {RElement} from '../interfaces/renderer'; import {RElement} from '../interfaces/renderer';
import {isContentQueryHost} from '../interfaces/type_checks'; import {isContentQueryHost, isDirectiveHost} from '../interfaces/type_checks';
import {BINDING_INDEX, HEADER_OFFSET, LView, RENDERER, TVIEW, T_HOST} from '../interfaces/view'; import {BINDING_INDEX, HEADER_OFFSET, LView, RENDERER, TVIEW, T_HOST} from '../interfaces/view';
import {assertNodeType} from '../node_assert'; import {assertNodeType} from '../node_assert';
import {appendChild} from '../node_manipulation'; import {appendChild} from '../node_manipulation';
@ -23,7 +23,7 @@ import {getInitialStylingValue, hasClassInput, hasStyleInput} from '../styling_n
import {setUpAttributes} from '../util/attrs_utils'; import {setUpAttributes} from '../util/attrs_utils';
import {getNativeByTNode, getTNode} from '../util/view_utils'; import {getNativeByTNode, getTNode} from '../util/view_utils';
import {createDirectivesAndLocals, elementCreate, executeContentQueries, getOrCreateTNode, initializeTNodeInputs, renderInitialStyling, resolveDirectives, setInputsForProperty} from './shared'; import {createDirectivesInstances, elementCreate, executeContentQueries, getOrCreateTNode, initializeTNodeInputs, renderInitialStyling, resolveDirectives, saveResolvedLocalsInData, setInputsForProperty} from './shared';
@ -98,8 +98,13 @@ export function ɵɵelementStart(
} }
} }
createDirectivesAndLocals(tView, lView, tNode); if (isDirectiveHost(tNode)) {
executeContentQueries(tView, tNode, lView); createDirectivesInstances(tView, lView, tNode);
executeContentQueries(tView, tNode, lView);
}
if (localRefs != null) {
saveResolvedLocalsInData(lView, tNode);
}
} }
/** /**

View File

@ -10,14 +10,14 @@ import {assertHasParent} from '../assert';
import {attachPatchData} from '../context_discovery'; import {attachPatchData} from '../context_discovery';
import {registerPostOrderHooks} from '../hooks'; import {registerPostOrderHooks} from '../hooks';
import {TAttributes, TNodeType} from '../interfaces/node'; import {TAttributes, TNodeType} from '../interfaces/node';
import {isContentQueryHost} from '../interfaces/type_checks'; import {isContentQueryHost, isDirectiveHost} from '../interfaces/type_checks';
import {BINDING_INDEX, HEADER_OFFSET, RENDERER, TVIEW, T_HOST} from '../interfaces/view'; import {BINDING_INDEX, HEADER_OFFSET, RENDERER, TVIEW, T_HOST} from '../interfaces/view';
import {assertNodeType} from '../node_assert'; import {assertNodeType} from '../node_assert';
import {appendChild} from '../node_manipulation'; import {appendChild} from '../node_manipulation';
import {getIsParent, getLView, getPreviousOrParentTNode, setIsNotParent, setPreviousOrParentTNode} from '../state'; import {getIsParent, getLView, getPreviousOrParentTNode, setIsNotParent, setPreviousOrParentTNode} from '../state';
import {registerInitialStylingOnTNode} from '../styling_next/instructions'; import {registerInitialStylingOnTNode} from '../styling_next/instructions';
import {createDirectivesAndLocals, executeContentQueries, getOrCreateTNode, resolveDirectives} from './shared'; import {createDirectivesInstances, executeContentQueries, getOrCreateTNode, resolveDirectives, saveResolvedLocalsInData} from './shared';
@ -61,6 +61,7 @@ export function ɵɵelementContainerStart(
} }
appendChild(native, tNode, lView); appendChild(native, tNode, lView);
attachPatchData(native, lView);
if (tView.firstTemplatePass) { if (tView.firstTemplatePass) {
ngDevMode && ngDevMode.firstTemplatePass++; ngDevMode && ngDevMode.firstTemplatePass++;
@ -70,9 +71,14 @@ export function ɵɵelementContainerStart(
} }
} }
createDirectivesAndLocals(tView, lView, tNode); if (isDirectiveHost(tNode)) {
attachPatchData(native, lView); createDirectivesInstances(tView, lView, tNode);
executeContentQueries(tView, tNode, lView); executeContentQueries(tView, tNode, lView);
}
if (localRefs != null) {
saveResolvedLocalsInData(lView, tNode);
}
} }
/** /**

View File

@ -244,8 +244,9 @@ function wrapListener(
// In order to be backwards compatible with View Engine, events on component host nodes // In order to be backwards compatible with View Engine, events on component host nodes
// must also mark the component view itself dirty (i.e. the view that it owns). // must also mark the component view itself dirty (i.e. the view that it owns).
const startView = const startView = tNode.flags & TNodeFlags.isComponentHost ?
tNode.flags & TNodeFlags.isComponent ? getComponentViewByIndex(tNode.index, lView) : lView; getComponentViewByIndex(tNode.index, lView) :
lView;
// See interfaces/view.ts for more on LViewFlags.ManualOnPush // See interfaces/view.ts for more on LViewFlags.ManualOnPush
if ((lView[FLAGS] & LViewFlags.ManualOnPush) === 0) { if ((lView[FLAGS] & LViewFlags.ManualOnPush) === 0) {

View File

@ -161,7 +161,8 @@ export const TNodeConstructor = class TNode implements ITNode {
if (this.flags & TNodeFlags.hasClassInput) flags.push('TNodeFlags.hasClassInput'); if (this.flags & TNodeFlags.hasClassInput) flags.push('TNodeFlags.hasClassInput');
if (this.flags & TNodeFlags.hasContentQuery) flags.push('TNodeFlags.hasContentQuery'); if (this.flags & TNodeFlags.hasContentQuery) flags.push('TNodeFlags.hasContentQuery');
if (this.flags & TNodeFlags.hasStyleInput) flags.push('TNodeFlags.hasStyleInput'); if (this.flags & TNodeFlags.hasStyleInput) flags.push('TNodeFlags.hasStyleInput');
if (this.flags & TNodeFlags.isComponent) flags.push('TNodeFlags.isComponent'); if (this.flags & TNodeFlags.isComponentHost) flags.push('TNodeFlags.isComponentHost');
if (this.flags & TNodeFlags.isDirectiveHost) flags.push('TNodeFlags.isDirectiveHost');
if (this.flags & TNodeFlags.isDetached) flags.push('TNodeFlags.isDetached'); if (this.flags & TNodeFlags.isDetached) flags.push('TNodeFlags.isDetached');
if (this.flags & TNodeFlags.isProjected) flags.push('TNodeFlags.isProjected'); if (this.flags & TNodeFlags.isProjected) flags.push('TNodeFlags.isProjected');
return flags.join('|'); return flags.join('|');

View File

@ -25,7 +25,7 @@ import {INJECTOR_BLOOM_PARENT_SIZE, NodeInjectorFactory} from '../interfaces/inj
import {AttributeMarker, InitialInputData, InitialInputs, LocalRefExtractor, PropertyAliasValue, PropertyAliases, TAttributes, TContainerNode, TElementContainerNode, TElementNode, TIcuContainerNode, TNode, TNodeFlags, TNodeProviderIndexes, TNodeType, TProjectionNode, TViewNode} from '../interfaces/node'; import {AttributeMarker, InitialInputData, InitialInputs, LocalRefExtractor, PropertyAliasValue, PropertyAliases, TAttributes, TContainerNode, TElementContainerNode, TElementNode, TIcuContainerNode, TNode, TNodeFlags, TNodeProviderIndexes, TNodeType, TProjectionNode, TViewNode} from '../interfaces/node';
import {RComment, RElement, RText, Renderer3, RendererFactory3, isProceduralRenderer} from '../interfaces/renderer'; import {RComment, RElement, RText, Renderer3, RendererFactory3, isProceduralRenderer} from '../interfaces/renderer';
import {SanitizerFn} from '../interfaces/sanitization'; import {SanitizerFn} from '../interfaces/sanitization';
import {isComponent, isComponentDef, isContentQueryHost, isLContainer, isRootView} from '../interfaces/type_checks'; import {isComponentDef, isComponentHost, isContentQueryHost, isLContainer, isRootView} from '../interfaces/type_checks';
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';
@ -523,18 +523,13 @@ export function executeContentQueries(tView: TView, tNode: TNode, lView: LView)
/** /**
* Creates directive instances and populates local refs. * Creates directive instances.
*
* @param localRefs Local refs of the node in question
* @param localRefExtractor mapping function that extracts local ref value from TNode
*/ */
export function createDirectivesAndLocals( export function createDirectivesInstances(
tView: TView, lView: LView, tNode: TElementNode | TContainerNode | TElementContainerNode, tView: TView, lView: LView, tNode: TElementNode | TContainerNode | TElementContainerNode) {
localRefExtractor: LocalRefExtractor = getNativeByTNode) {
if (!getBindingsEnabled()) return; if (!getBindingsEnabled()) return;
instantiateAllDirectives(tView, lView, tNode); instantiateAllDirectives(tView, lView, tNode);
invokeDirectivesHostBindings(tView, lView, tNode); invokeDirectivesHostBindings(tView, lView, tNode);
saveResolvedLocalsInData(lView, tNode, localRefExtractor);
setActiveHostElement(null); setActiveHostElement(null);
} }
@ -542,8 +537,8 @@ export function createDirectivesAndLocals(
* Takes a list of local names and indices and pushes the resolved local variable values * Takes a list of local names and indices and pushes the resolved local variable values
* to LView in the same order as they are loaded in the template with load(). * to LView in the same order as they are loaded in the template with load().
*/ */
function saveResolvedLocalsInData( export function saveResolvedLocalsInData(
viewData: LView, tNode: TNode, localRefExtractor: LocalRefExtractor): void { viewData: LView, tNode: TNode, localRefExtractor: LocalRefExtractor = getNativeByTNode): void {
const localNames = tNode.localNames; const localNames = tNode.localNames;
if (localNames) { if (localNames) {
let localIndex = tNode.index + 1; let localIndex = tNode.index + 1;
@ -866,7 +861,7 @@ export function elementPropertyInternal<T>(
if (!nativeOnly && (inputData = initializeTNodeInputs(tView, tNode)) && if (!nativeOnly && (inputData = initializeTNodeInputs(tView, tNode)) &&
(dataValue = inputData[propName])) { (dataValue = inputData[propName])) {
setInputsForProperty(lView, dataValue, value); setInputsForProperty(lView, dataValue, value);
if (isComponent(tNode)) markDirtyIfOnPush(lView, index + HEADER_OFFSET); if (isComponentHost(tNode)) markDirtyIfOnPush(lView, index + HEADER_OFFSET);
if (ngDevMode) { if (ngDevMode) {
if (tNode.type === TNodeType.Element || tNode.type === TNodeType.Container) { if (tNode.type === TNodeType.Element || tNode.type === TNodeType.Container) {
/** /**
@ -1199,7 +1194,7 @@ function findDirectiveMatches(
diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, viewData), tView, def.type); diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, viewData), tView, def.type);
if (isComponentDef(def)) { if (isComponentDef(def)) {
if (tNode.flags & TNodeFlags.isComponent) throwMultipleComponentError(tNode); if (tNode.flags & TNodeFlags.isComponentHost) throwMultipleComponentError(tNode);
markAsComponentHost(tView, tNode); markAsComponentHost(tView, tNode);
// The component is always stored first with directives after. // The component is always stored first with directives after.
matches.unshift(def); matches.unshift(def);
@ -1219,7 +1214,7 @@ function findDirectiveMatches(
*/ */
export function markAsComponentHost(tView: TView, hostTNode: TNode): void { export function markAsComponentHost(tView: TView, hostTNode: TNode): void {
ngDevMode && assertFirstTemplatePass(tView); ngDevMode && assertFirstTemplatePass(tView);
hostTNode.flags = TNodeFlags.isComponent; hostTNode.flags = TNodeFlags.isComponentHost;
(tView.components || (tView.components = ngDevMode ? new TViewComponents !() : [ (tView.components || (tView.components = ngDevMode ? new TViewComponents !() : [
])).push(hostTNode.index); ])).push(hostTNode.index);
} }
@ -1268,14 +1263,14 @@ function saveNameToExportMap(
export function initNodeFlags(tNode: TNode, index: number, numberOfDirectives: number) { export function initNodeFlags(tNode: TNode, index: number, numberOfDirectives: number) {
const flags = tNode.flags; const flags = tNode.flags;
ngDevMode && assertEqual( ngDevMode && assertEqual(
flags === 0 || flags === TNodeFlags.isComponent, true, flags === 0 || flags === TNodeFlags.isComponentHost, true,
'expected node flags to not be initialized'); 'expected node flags to not be initialized');
ngDevMode && assertNotEqual( ngDevMode && assertNotEqual(
numberOfDirectives, tNode.directiveEnd - tNode.directiveStart, numberOfDirectives, tNode.directiveEnd - tNode.directiveStart,
'Reached the max number of directives'); 'Reached the max number of directives');
// When the first directive is created on a node, save the index // When the first directive is created on a node, save the index
tNode.flags = flags & TNodeFlags.isComponent; tNode.flags = (flags & TNodeFlags.isComponentHost) | TNodeFlags.isDirectiveHost;
tNode.directiveStart = index; tNode.directiveStart = index;
tNode.directiveEnd = index + numberOfDirectives; tNode.directiveEnd = index + numberOfDirectives;
tNode.providerIndexes = index; tNode.providerIndexes = index;

View File

@ -45,23 +45,28 @@ export const enum TNodeType {
* Corresponds to the TNode.flags property. * Corresponds to the TNode.flags property.
*/ */
export const enum TNodeFlags { export const enum TNodeFlags {
/** This bit is set if the node is a component */ /** This bit is set if the node is a host for any directive (including a component) */
isComponent = 0b000001, isDirectiveHost = 0b00000001,
/**
* This bit is set if the node is a host for a component. Setting this bit implies that the
* isDirectiveHost bit is set as well. */
isComponentHost = 0b00000010,
/** This bit is set if the node has been projected */ /** This bit is set if the node has been projected */
isProjected = 0b000010, isProjected = 0b00000100,
/** This bit is set if any directive on this node has content queries */ /** This bit is set if any directive on this node has content queries */
hasContentQuery = 0b000100, hasContentQuery = 0b00001000,
/** This bit is set if the node has any "class" inputs */ /** This bit is set if the node has any "class" inputs */
hasClassInput = 0b001000, hasClassInput = 0b00010000,
/** This bit is set if the node has any "style" inputs */ /** This bit is set if the node has any "style" inputs */
hasStyleInput = 0b010000, hasStyleInput = 0b00100000,
/** This bit is set if the node has been detached by i18n */ /** This bit is set if the node has been detached by i18n */
isDetached = 0b100000, isDetached = 0b01000000,
} }
/** /**

View File

@ -34,8 +34,12 @@ export function isContentQueryHost(tNode: TNode): boolean {
return (tNode.flags & TNodeFlags.hasContentQuery) !== 0; return (tNode.flags & TNodeFlags.hasContentQuery) !== 0;
} }
export function isComponent(tNode: TNode): boolean { export function isComponentHost(tNode: TNode): boolean {
return (tNode.flags & TNodeFlags.isComponent) === TNodeFlags.isComponent; return (tNode.flags & TNodeFlags.isComponentHost) === TNodeFlags.isComponentHost;
}
export function isDirectiveHost(tNode: TNode): boolean {
return (tNode.flags & TNodeFlags.isDirectiveHost) === TNodeFlags.isDirectiveHost;
} }
export function isComponentDef<T>(def: DirectiveDef<T>): def is ComponentDef<T> { export function isComponentDef<T>(def: DirectiveDef<T>): def is ComponentDef<T> {

View File

@ -526,7 +526,7 @@ function getRenderParent(tNode: TNode, currentView: LView): RElement|null {
} }
ngDevMode && assertNodeType(parentTNode, TNodeType.Element); ngDevMode && assertNodeType(parentTNode, TNodeType.Element);
if (parentTNode.flags & TNodeFlags.isComponent) { if (parentTNode.flags & TNodeFlags.isComponentHost) {
const tData = currentView[TVIEW].data; const tData = currentView[TVIEW].data;
const tNode = tData[parentTNode.index] as TNode; const tNode = tData[parentTNode.index] as TNode;
const encapsulation = (tData[tNode.directiveStart] as ComponentDef<any>).encapsulation; const encapsulation = (tData[tNode.directiveStart] as ComponentDef<any>).encapsulation;

View File

@ -24,7 +24,7 @@ import {addToViewTree, createLContainer, createLView, renderView} from './instru
import {ACTIVE_INDEX, CONTAINER_HEADER_OFFSET, LContainer, VIEW_REFS} from './interfaces/container'; import {ACTIVE_INDEX, CONTAINER_HEADER_OFFSET, LContainer, VIEW_REFS} from './interfaces/container';
import {TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeType, TViewNode} from './interfaces/node'; import {TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeType, TViewNode} from './interfaces/node';
import {RComment, RElement, isProceduralRenderer} from './interfaces/renderer'; import {RComment, RElement, isProceduralRenderer} from './interfaces/renderer';
import {isComponent, isLContainer, isLView, isRootView} from './interfaces/type_checks'; import {isComponentHost, isLContainer, isLView, isRootView} from './interfaces/type_checks';
import {CONTEXT, DECLARATION_LCONTAINER, LView, LViewFlags, QUERIES, RENDERER, TView, T_HOST} from './interfaces/view'; import {CONTEXT, DECLARATION_LCONTAINER, LView, LViewFlags, QUERIES, RENDERER, TView, T_HOST} from './interfaces/view';
import {assertNodeOfPossibleTypes} from './node_assert'; import {assertNodeOfPossibleTypes} from './node_assert';
import {addRemoveViewFromContainer, appendChild, detachView, getBeforeNodeForView, insertView, nativeInsertBefore, nativeNextSibling, nativeParentNode, removeView} from './node_manipulation'; import {addRemoveViewFromContainer, appendChild, detachView, getBeforeNodeForView, insertView, nativeInsertBefore, nativeNextSibling, nativeParentNode, removeView} from './node_manipulation';
@ -371,7 +371,7 @@ export function injectChangeDetectorRef(isPipe = false): ViewEngine_ChangeDetect
*/ */
function createViewRef( function createViewRef(
hostTNode: TNode, hostView: LView, isPipe: boolean): ViewEngine_ChangeDetectorRef { hostTNode: TNode, hostView: LView, isPipe: boolean): ViewEngine_ChangeDetectorRef {
if (isComponent(hostTNode) && !isPipe) { if (isComponentHost(hostTNode) && !isPipe) {
const componentIndex = hostTNode.directiveStart; const componentIndex = hostTNode.directiveStart;
const componentView = getComponentViewByIndex(hostTNode.index, hostView); const componentView = getComponentViewByIndex(hostTNode.index, hostView);
return new ViewRef(componentView, null, componentIndex); return new ViewRef(componentView, null, componentIndex);

View File

@ -204,7 +204,7 @@
"name": "concatString" "name": "concatString"
}, },
{ {
"name": "createDirectivesAndLocals" "name": "createDirectivesInstances"
}, },
{ {
"name": "createLView" "name": "createLView"
@ -455,6 +455,9 @@
{ {
"name": "isCssClassMatching" "name": "isCssClassMatching"
}, },
{
"name": "isDirectiveHost"
},
{ {
"name": "isFactory" "name": "isFactory"
}, },
@ -698,4 +701,4 @@
{ {
"name": "ɵɵtext" "name": "ɵɵtext"
} }
] ]

View File

@ -491,4 +491,4 @@
{ {
"name": "ɵɵtext" "name": "ɵɵtext"
} }
] ]

View File

@ -537,7 +537,7 @@
"name": "createContainerRef" "name": "createContainerRef"
}, },
{ {
"name": "createDirectivesAndLocals" "name": "createDirectivesInstances"
}, },
{ {
"name": "createElementRef" "name": "createElementRef"
@ -987,10 +987,10 @@
"name": "isAnimationProp" "name": "isAnimationProp"
}, },
{ {
"name": "isComponent" "name": "isComponentDef"
}, },
{ {
"name": "isComponentDef" "name": "isComponentHost"
}, },
{ {
"name": "isContentQueryHost" "name": "isContentQueryHost"
@ -1007,6 +1007,9 @@
{ {
"name": "isDevMode" "name": "isDevMode"
}, },
{
"name": "isDirectiveHost"
},
{ {
"name": "isFactory" "name": "isFactory"
}, },