|
|
|
@ -30,7 +30,7 @@ import {StylingContext} from '../interfaces/styling';
|
|
|
|
|
import {BINDING_INDEX, CHILD_HEAD, CHILD_TAIL, CLEANUP, CONTEXT, DECLARATION_VIEW, ExpandoInstructions, FLAGS, HEADER_OFFSET, HOST, INJECTOR, InitPhaseState, LView, LViewFlags, NEXT, PARENT, QUERIES, RENDERER, RENDERER_FACTORY, RootContext, RootContextFlags, SANITIZER, TData, TVIEW, TView, T_HOST} from '../interfaces/view';
|
|
|
|
|
import {assertNodeOfPossibleTypes, assertNodeType} from '../node_assert';
|
|
|
|
|
import {isNodeMatchingSelectorList} from '../node_selector_matcher';
|
|
|
|
|
import {enterView, getBindingsEnabled, getCheckNoChangesMode, getIsParent, getLView, getNamespace, getPreviousOrParentTNode, incrementActiveDirectiveId, isCreationMode, leaveView, resetComponentState, setActiveHostElement, setBindingRoot, setCheckNoChangesMode, setCurrentDirectiveDef, setCurrentQueryIndex, setIsParent, setPreviousOrParentTNode, setSelectedIndex, ɵɵnamespaceHTML} from '../state';
|
|
|
|
|
import {enterView, getBindingsEnabled, getCheckNoChangesMode, getIsParent, getLView, getNamespace, getPreviousOrParentTNode, getSelectedIndex, incrementActiveDirectiveId, isCreationMode, leaveView, resetComponentState, setActiveHostElement, setBindingRoot, setCheckNoChangesMode, setCurrentDirectiveDef, setCurrentQueryIndex, setIsParent, setPreviousOrParentTNode, setSelectedIndex, ɵɵnamespaceHTML} from '../state';
|
|
|
|
|
import {initializeStaticContext as initializeStaticStylingContext} from '../styling/class_and_style_bindings';
|
|
|
|
|
import {ANIMATION_PROP_PREFIX, isAnimationProp} from '../styling/util';
|
|
|
|
|
import {NO_CHANGE} from '../tokens';
|
|
|
|
@ -101,51 +101,55 @@ export function refreshDescendantViews(lView: LView) {
|
|
|
|
|
|
|
|
|
|
/** Sets the host bindings for the current view. */
|
|
|
|
|
export function setHostBindings(tView: TView, viewData: LView): void {
|
|
|
|
|
if (tView.expandoInstructions) {
|
|
|
|
|
let bindingRootIndex = viewData[BINDING_INDEX] = tView.expandoStartIndex;
|
|
|
|
|
setBindingRoot(bindingRootIndex);
|
|
|
|
|
let currentDirectiveIndex = -1;
|
|
|
|
|
let currentElementIndex = -1;
|
|
|
|
|
for (let i = 0; i < tView.expandoInstructions.length; i++) {
|
|
|
|
|
const instruction = tView.expandoInstructions[i];
|
|
|
|
|
if (typeof instruction === 'number') {
|
|
|
|
|
if (instruction <= 0) {
|
|
|
|
|
// Negative numbers mean that we are starting new EXPANDO block and need to update
|
|
|
|
|
// the current element and directive index.
|
|
|
|
|
currentElementIndex = -instruction;
|
|
|
|
|
setActiveHostElement(currentElementIndex);
|
|
|
|
|
const selectedIndex = getSelectedIndex();
|
|
|
|
|
try {
|
|
|
|
|
if (tView.expandoInstructions) {
|
|
|
|
|
let bindingRootIndex = viewData[BINDING_INDEX] = tView.expandoStartIndex;
|
|
|
|
|
setBindingRoot(bindingRootIndex);
|
|
|
|
|
let currentDirectiveIndex = -1;
|
|
|
|
|
let currentElementIndex = -1;
|
|
|
|
|
for (let i = 0; i < tView.expandoInstructions.length; i++) {
|
|
|
|
|
const instruction = tView.expandoInstructions[i];
|
|
|
|
|
if (typeof instruction === 'number') {
|
|
|
|
|
if (instruction <= 0) {
|
|
|
|
|
// Negative numbers mean that we are starting new EXPANDO block and need to update
|
|
|
|
|
// the current element and directive index.
|
|
|
|
|
currentElementIndex = -instruction;
|
|
|
|
|
setActiveHostElement(currentElementIndex);
|
|
|
|
|
|
|
|
|
|
// Injector block and providers are taken into account.
|
|
|
|
|
const providerCount = (tView.expandoInstructions[++i] as number);
|
|
|
|
|
bindingRootIndex += INJECTOR_BLOOM_PARENT_SIZE + providerCount;
|
|
|
|
|
// Injector block and providers are taken into account.
|
|
|
|
|
const providerCount = (tView.expandoInstructions[++i] as number);
|
|
|
|
|
bindingRootIndex += INJECTOR_BLOOM_PARENT_SIZE + providerCount;
|
|
|
|
|
|
|
|
|
|
currentDirectiveIndex = bindingRootIndex;
|
|
|
|
|
currentDirectiveIndex = bindingRootIndex;
|
|
|
|
|
} else {
|
|
|
|
|
// This is either the injector size (so the binding root can skip over directives
|
|
|
|
|
// and get to the first set of host bindings on this node) or the host var count
|
|
|
|
|
// (to get to the next set of host bindings on this node).
|
|
|
|
|
bindingRootIndex += instruction;
|
|
|
|
|
}
|
|
|
|
|
setBindingRoot(bindingRootIndex);
|
|
|
|
|
} else {
|
|
|
|
|
// This is either the injector size (so the binding root can skip over directives
|
|
|
|
|
// and get to the first set of host bindings on this node) or the host var count
|
|
|
|
|
// (to get to the next set of host bindings on this node).
|
|
|
|
|
bindingRootIndex += instruction;
|
|
|
|
|
}
|
|
|
|
|
setBindingRoot(bindingRootIndex);
|
|
|
|
|
} else {
|
|
|
|
|
// If it's not a number, it's a host binding function that needs to be executed.
|
|
|
|
|
if (instruction !== null) {
|
|
|
|
|
viewData[BINDING_INDEX] = bindingRootIndex;
|
|
|
|
|
const hostCtx = unwrapRNode(viewData[currentDirectiveIndex]);
|
|
|
|
|
instruction(RenderFlags.Update, hostCtx, currentElementIndex);
|
|
|
|
|
// If it's not a number, it's a host binding function that needs to be executed.
|
|
|
|
|
if (instruction !== null) {
|
|
|
|
|
viewData[BINDING_INDEX] = bindingRootIndex;
|
|
|
|
|
const hostCtx = unwrapRNode(viewData[currentDirectiveIndex]);
|
|
|
|
|
instruction(RenderFlags.Update, hostCtx, currentElementIndex);
|
|
|
|
|
|
|
|
|
|
// Each directive gets a uniqueId value that is the same for both
|
|
|
|
|
// create and update calls when the hostBindings function is called. The
|
|
|
|
|
// directive uniqueId is not set anywhere--it is just incremented between
|
|
|
|
|
// each hostBindings call and is useful for helping instruction code
|
|
|
|
|
// uniquely determine which directive is currently active when executed.
|
|
|
|
|
incrementActiveDirectiveId();
|
|
|
|
|
// Each directive gets a uniqueId value that is the same for both
|
|
|
|
|
// create and update calls when the hostBindings function is called. The
|
|
|
|
|
// directive uniqueId is not set anywhere--it is just incremented between
|
|
|
|
|
// each hostBindings call and is useful for helping instruction code
|
|
|
|
|
// uniquely determine which directive is currently active when executed.
|
|
|
|
|
incrementActiveDirectiveId();
|
|
|
|
|
}
|
|
|
|
|
currentDirectiveIndex++;
|
|
|
|
|
}
|
|
|
|
|
currentDirectiveIndex++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} finally {
|
|
|
|
|
setActiveHostElement(selectedIndex);
|
|
|
|
|
}
|
|
|
|
|
setActiveHostElement(null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Refreshes content queries for all directives in the given view. */
|
|
|
|
@ -431,12 +435,8 @@ export function renderEmbeddedTemplate<T>(viewToRender: LView, tView: TView, con
|
|
|
|
|
|
|
|
|
|
oldView = enterView(viewToRender, viewToRender[T_HOST]);
|
|
|
|
|
resetPreOrderHookFlags(viewToRender);
|
|
|
|
|
ɵɵnamespaceHTML();
|
|
|
|
|
executeTemplate(tView.template !, getRenderFlags(viewToRender), context);
|
|
|
|
|
|
|
|
|
|
// Reset the selected index so we can assert that `select` was called later
|
|
|
|
|
setSelectedIndex(-1);
|
|
|
|
|
|
|
|
|
|
tView.template !(getRenderFlags(viewToRender), context);
|
|
|
|
|
// This must be set to false immediately after the first creation run because in an
|
|
|
|
|
// ngFor loop, all the views will be created together before update mode runs and turns
|
|
|
|
|
// off firstTemplatePass. If we don't set it here, instances will perform directive
|
|
|
|
@ -465,14 +465,7 @@ function renderComponentOrTemplate<T>(
|
|
|
|
|
|
|
|
|
|
if (creationModeIsActive) {
|
|
|
|
|
// creation mode pass
|
|
|
|
|
if (templateFn) {
|
|
|
|
|
ɵɵnamespaceHTML();
|
|
|
|
|
|
|
|
|
|
// Reset the selected index so we can assert that `select` was called later
|
|
|
|
|
setSelectedIndex(-1);
|
|
|
|
|
|
|
|
|
|
templateFn(RenderFlags.Create, context);
|
|
|
|
|
}
|
|
|
|
|
templateFn && executeTemplate(templateFn, RenderFlags.Create, context);
|
|
|
|
|
|
|
|
|
|
refreshDescendantViews(hostView);
|
|
|
|
|
hostView[FLAGS] &= ~LViewFlags.CreationMode;
|
|
|
|
@ -480,7 +473,7 @@ function renderComponentOrTemplate<T>(
|
|
|
|
|
|
|
|
|
|
// update mode pass
|
|
|
|
|
resetPreOrderHookFlags(hostView);
|
|
|
|
|
templateFn && templateFn(RenderFlags.Update, context);
|
|
|
|
|
templateFn && executeTemplate(templateFn, RenderFlags.Update, context);
|
|
|
|
|
refreshDescendantViews(hostView);
|
|
|
|
|
} finally {
|
|
|
|
|
if (normalExecutionPath && !creationModeIsActive && rendererFactory.end) {
|
|
|
|
@ -490,6 +483,17 @@ function renderComponentOrTemplate<T>(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function executeTemplate<T>(templateFn: ComponentTemplate<T>, rf: RenderFlags, context: T) {
|
|
|
|
|
ɵɵnamespaceHTML();
|
|
|
|
|
const prevSelectedIndex = getSelectedIndex();
|
|
|
|
|
try {
|
|
|
|
|
setActiveHostElement(null);
|
|
|
|
|
templateFn(rf, context);
|
|
|
|
|
} finally {
|
|
|
|
|
setSelectedIndex(prevSelectedIndex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This function returns the default configuration of rendering flags depending on when the
|
|
|
|
|
* template is in creation mode or update mode. Update block and create block are
|
|
|
|
@ -1073,26 +1077,29 @@ function invokeDirectivesHostBindings(tView: TView, viewData: LView, tNode: TNod
|
|
|
|
|
const expando = tView.expandoInstructions !;
|
|
|
|
|
const firstTemplatePass = tView.firstTemplatePass;
|
|
|
|
|
const elementIndex = tNode.index - HEADER_OFFSET;
|
|
|
|
|
setActiveHostElement(elementIndex);
|
|
|
|
|
const selectedIndex = getSelectedIndex();
|
|
|
|
|
try {
|
|
|
|
|
setActiveHostElement(elementIndex);
|
|
|
|
|
|
|
|
|
|
for (let i = start; i < end; i++) {
|
|
|
|
|
const def = tView.data[i] as DirectiveDef<any>;
|
|
|
|
|
const directive = viewData[i];
|
|
|
|
|
if (def.hostBindings) {
|
|
|
|
|
invokeHostBindingsInCreationMode(def, expando, directive, tNode, firstTemplatePass);
|
|
|
|
|
for (let i = start; i < end; i++) {
|
|
|
|
|
const def = tView.data[i] as DirectiveDef<any>;
|
|
|
|
|
const directive = viewData[i];
|
|
|
|
|
if (def.hostBindings) {
|
|
|
|
|
invokeHostBindingsInCreationMode(def, expando, directive, tNode, firstTemplatePass);
|
|
|
|
|
|
|
|
|
|
// Each directive gets a uniqueId value that is the same for both
|
|
|
|
|
// create and update calls when the hostBindings function is called. The
|
|
|
|
|
// directive uniqueId is not set anywhere--it is just incremented between
|
|
|
|
|
// each hostBindings call and is useful for helping instruction code
|
|
|
|
|
// uniquely determine which directive is currently active when executed.
|
|
|
|
|
incrementActiveDirectiveId();
|
|
|
|
|
} else if (firstTemplatePass) {
|
|
|
|
|
expando.push(null);
|
|
|
|
|
// Each directive gets a uniqueId value that is the same for both
|
|
|
|
|
// create and update calls when the hostBindings function is called. The
|
|
|
|
|
// directive uniqueId is not set anywhere--it is just incremented between
|
|
|
|
|
// each hostBindings call and is useful for helping instruction code
|
|
|
|
|
// uniquely determine which directive is currently active when executed.
|
|
|
|
|
incrementActiveDirectiveId();
|
|
|
|
|
} else if (firstTemplatePass) {
|
|
|
|
|
expando.push(null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} finally {
|
|
|
|
|
setActiveHostElement(selectedIndex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setActiveHostElement(null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function invokeHostBindingsInCreationMode(
|
|
|
|
@ -1685,14 +1692,8 @@ export function checkView<T>(hostView: LView, component: T) {
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
resetPreOrderHookFlags(hostView);
|
|
|
|
|
ɵɵnamespaceHTML();
|
|
|
|
|
creationMode && executeViewQueryFn(RenderFlags.Create, hostTView, component);
|
|
|
|
|
|
|
|
|
|
// Reset the selected index so we can assert that `select` was called later
|
|
|
|
|
setSelectedIndex(-1);
|
|
|
|
|
|
|
|
|
|
templateFn(getRenderFlags(hostView), component);
|
|
|
|
|
|
|
|
|
|
executeTemplate(templateFn, getRenderFlags(hostView), component);
|
|
|
|
|
refreshDescendantViews(hostView);
|
|
|
|
|
// Only check view queries again in creation mode if there are static view queries
|
|
|
|
|
if (!creationMode || hostTView.staticViewQueries) {
|
|
|
|
|