refactor(ivy): Explicitly pass in `TView` (#35069)

- Adds `TView` into `LFrame`, read the `TView` from `LView` on `enterView`.
- Before this change the `TView` was ofter looked up from `LView` as `lView[TVIEW]`. This is suboptimal since reading from an Array, requires that the read checks array size before the read. This means that such a read has a much higher cost than reading from the property directly. By passing in the `TView` explicitly it makes the code more explicit and faster.
- Some rearrangements of arguments so that `TView` would come before `LView` for consistency.

PR Close #35069
This commit is contained in:
Miško Hevery 2020-01-30 14:57:44 -08:00
parent 770980de69
commit d528dedd50
47 changed files with 494 additions and 445 deletions

View File

@ -144,9 +144,9 @@ export function renderComponent<T>(
componentView, componentDef, rootView, rootContext, opts.hostFeatures || null);
// create mode pass
renderView(rootView, rootTView, null);
renderView(rootTView, rootView, null);
// update mode pass
refreshView(rootView, rootTView, null, null);
refreshView(rootTView, rootView, null, null);
} finally {
leaveView();

View File

@ -174,7 +174,7 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
const componentView = createRootComponentView(
hostRNode, this.componentDef, rootLView, rendererFactory, hostRenderer, addVersion, null);
tElementNode = getTNode(0, rootLView) as TElementNode;
tElementNode = getTNode(rootLView[TVIEW], 0) as TElementNode;
if (projectableNodes) {
// projectable nodes can be passed as array of arrays or an array of iterables (ngUpgrade
@ -190,7 +190,7 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
component = createRootComponent(
componentView, this.componentDef, rootLView, rootContext, [LifecycleHooksFeature]);
renderView(rootLView, rootTView, null);
renderView(rootTView, rootLView, null);
} finally {
leaveView();
}

View File

@ -18,7 +18,7 @@ import {NodeInjectorFactory} from './interfaces/injector';
import {TContainerNode, TDirectiveHostNode, TElementContainerNode, TElementNode, TNodeProviderIndexes} from './interfaces/node';
import {isComponentDef} from './interfaces/type_checks';
import {LView, TData, TVIEW, TView} from './interfaces/view';
import {getLView, getPreviousOrParentTNode} from './state';
import {getLView, getPreviousOrParentTNode, getTView} from './state';
@ -42,8 +42,7 @@ import {getLView, getPreviousOrParentTNode} from './state';
*/
export function providersResolver<T>(
def: DirectiveDef<T>, providers: Provider[], viewProviders: Provider[]): void {
const lView = getLView();
const tView: TView = lView[TVIEW];
const tView = getTView();
if (tView.firstCreatePass) {
const isComponent = isComponentDef(def);
@ -71,8 +70,8 @@ function resolveProvider(
provider[i], tInjectables, lInjectablesBlueprint, isComponent, isViewProvider);
}
} else {
const tView = getTView();
const lView = getLView();
const tView = lView[TVIEW];
let token: any = isTypeProvider(provider) ? provider : resolveForwardRef(provider.provide);
let providerFactory: () => any = providerToFactory(provider);

View File

@ -13,7 +13,6 @@ import {InertBodyHelper} from '../sanitization/inert_body';
import {_sanitizeUrl, sanitizeSrcset} from '../sanitization/url_sanitizer';
import {addAllToArray} from '../util/array_utils';
import {assertDataInRange, assertDefined, assertEqual} from '../util/assert';
import {bindingUpdated} from './bindings';
import {attachPatchData} from './context_discovery';
import {setDelayProjection} from './instructions/all';
@ -28,7 +27,7 @@ import {SanitizerFn} from './interfaces/sanitization';
import {isLContainer} from './interfaces/type_checks';
import {HEADER_OFFSET, LView, RENDERER, TVIEW, TView, T_HOST} from './interfaces/view';
import {appendChild, applyProjection, createTextNode, nativeRemoveNode} from './node_manipulation';
import {getBindingIndex, getIsParent, getLView, getPreviousOrParentTNode, nextBindingIndex, setIsNotParent, setPreviousOrParentTNode} from './state';
import {getBindingIndex, getIsParent, getLView, getPreviousOrParentTNode, getTView, nextBindingIndex, setIsNotParent, setPreviousOrParentTNode} from './state';
import {renderStringify} from './util/misc_utils';
import {getNativeByIndex, getNativeByTNode, getTNode, load} from './util/view_utils';
@ -360,14 +359,13 @@ const parentIndexStack: number[] = [];
* @codeGenApi
*/
export function ɵɵi18nStart(index: number, message: string, subTemplateIndex?: number): void {
const lView = getLView();
const tView = lView[TVIEW];
const tView = getTView();
ngDevMode && assertDefined(tView, `tView should be defined`);
i18nIndexStack[++i18nIndexStackPointer] = index;
// We need to delay projections until `i18nEnd`
setDelayProjection(true);
if (tView.firstCreatePass && tView.data[index + HEADER_OFFSET] === null) {
i18nStartFirstPass(lView, tView, index, message, subTemplateIndex);
i18nStartFirstPass(getLView(), tView, index, message, subTemplateIndex);
}
}
@ -471,7 +469,7 @@ function i18nStartFirstPass(
}
if (i18nVarsCount > 0) {
allocExpando(lView, i18nVarsCount);
allocExpando(tView, lView, i18nVarsCount);
}
ngDevMode &&
@ -490,7 +488,8 @@ function i18nStartFirstPass(
}
function appendI18nNode(
tNode: TNode, parentTNode: TNode, previousTNode: TNode | null, lView: LView): TNode {
tView: TView, tNode: TNode, parentTNode: TNode, previousTNode: TNode | null,
lView: LView): TNode {
ngDevMode && ngDevMode.rendererMoveNode++;
const nextNode = tNode.next;
if (!previousTNode) {
@ -523,16 +522,16 @@ function appendI18nNode(
// If the placeholder to append is a projection, we need to move the projected nodes instead
if (tNode.type === TNodeType.Projection) {
applyProjection(lView, tNode as TProjectionNode);
applyProjection(tView, lView, tNode as TProjectionNode);
return tNode;
}
appendChild(getNativeByTNode(tNode, lView), tNode, lView);
appendChild(tView, lView, getNativeByTNode(tNode, lView), tNode);
const slotValue = lView[tNode.index];
if (tNode.type !== TNodeType.Container && isLContainer(slotValue)) {
// Nodes that inject ViewContainerRef also have a comment node that should be moved
appendChild(slotValue[NATIVE], tNode, lView);
appendChild(tView, lView, slotValue[NATIVE], tNode);
}
return tNode;
}
@ -657,9 +656,9 @@ export function ɵɵi18nPostprocess(
*/
export function ɵɵi18nEnd(): void {
const lView = getLView();
const tView = lView[TVIEW];
const tView = getTView();
ngDevMode && assertDefined(tView, `tView should be defined`);
i18nEndFirstPass(lView, tView);
i18nEndFirstPass(tView, lView);
// Stop delaying projections
setDelayProjection(false);
}
@ -667,7 +666,7 @@ export function ɵɵi18nEnd(): void {
/**
* See `i18nEnd` above.
*/
function i18nEndFirstPass(lView: LView, tView: TView) {
function i18nEndFirstPass(tView: TView, lView: LView) {
ngDevMode && assertEqual(
getBindingIndex(), tView.bindingStartIndex,
'i18nEnd should be called before any binding');
@ -680,16 +679,16 @@ function i18nEndFirstPass(lView: LView, tView: TView) {
const lastCreatedNode = getPreviousOrParentTNode();
// Read the instructions to insert/move/remove DOM elements
const visitedNodes = readCreateOpCodes(rootIndex, tI18n.create, lView);
const visitedNodes = readCreateOpCodes(rootIndex, tI18n.create, tView, lView);
// Remove deleted nodes
let index = rootIndex + 1;
while (index <= lastCreatedNode.index - HEADER_OFFSET) {
if (visitedNodes.indexOf(index) === -1) {
removeNode(index, lView, /* markAsDetached */ true);
removeNode(tView, lView, index, /* markAsDetached */ true);
}
// Check if an element has any local refs and skip them
const tNode = getTNode(index, lView);
const tNode = getTNode(tView, index);
if (tNode && (tNode.type === TNodeType.Element || tNode.type === TNodeType.ElementContainer) &&
tNode.localNames !== null) {
// Divide by 2 to get the number of local refs,
@ -705,12 +704,12 @@ function i18nEndFirstPass(lView: LView, tView: TView) {
* Creates and stores the dynamic TNode, and unhooks it from the tree for now.
*/
function createDynamicNodeAtIndex(
lView: LView, index: number, type: TNodeType, native: RElement | RText | null,
tView: TView, lView: LView, index: number, type: TNodeType, native: RElement | RText | null,
name: string | null): TElementNode|TIcuContainerNode {
const previousOrParentTNode = getPreviousOrParentTNode();
ngDevMode && assertDataInRange(lView, index + HEADER_OFFSET);
lView[index + HEADER_OFFSET] = native;
const tNode = getOrCreateTNode(lView[TVIEW], lView[T_HOST], index, type as any, name, null);
const tNode = getOrCreateTNode(tView, lView[T_HOST], index, type as any, name, null);
// We are creating a dynamic node, the previous tNode might not be pointing at this node.
// We will link ourselves into the tree later with `appendI18nNode`.
@ -722,7 +721,7 @@ function createDynamicNodeAtIndex(
}
function readCreateOpCodes(
index: number, createOpCodes: I18nMutateOpCodes, lView: LView): number[] {
index: number, createOpCodes: I18nMutateOpCodes, tView: TView, lView: LView): number[] {
const renderer = lView[RENDERER];
let currentTNode: TNode|null = null;
let previousTNode: TNode|null = null;
@ -735,7 +734,7 @@ function readCreateOpCodes(
ngDevMode && ngDevMode.rendererCreateTextNode++;
previousTNode = currentTNode;
currentTNode =
createDynamicNodeAtIndex(lView, textNodeIndex, TNodeType.Element, textRNode, null);
createDynamicNodeAtIndex(tView, lView, textNodeIndex, TNodeType.Element, textRNode, null);
visitedNodes.push(textNodeIndex);
setIsNotParent();
} else if (typeof opCode == 'number') {
@ -748,26 +747,27 @@ function readCreateOpCodes(
// top-level node and we should use the host node instead
destinationTNode = lView[T_HOST] !;
} else {
destinationTNode = getTNode(destinationNodeIndex, lView);
destinationTNode = getTNode(tView, destinationNodeIndex);
}
ngDevMode &&
assertDefined(
currentTNode !,
`You need to create or select a node before you can insert it into the DOM`);
previousTNode = appendI18nNode(currentTNode !, destinationTNode, previousTNode, lView);
previousTNode =
appendI18nNode(tView, currentTNode !, destinationTNode, previousTNode, lView);
break;
case I18nMutateOpCode.Select:
const nodeIndex = opCode >>> I18nMutateOpCode.SHIFT_REF;
visitedNodes.push(nodeIndex);
previousTNode = currentTNode;
currentTNode = getTNode(nodeIndex, lView);
currentTNode = getTNode(tView, nodeIndex);
if (currentTNode) {
setPreviousOrParentTNode(currentTNode, currentTNode.type === TNodeType.Element);
}
break;
case I18nMutateOpCode.ElementEnd:
const elementIndex = opCode >>> I18nMutateOpCode.SHIFT_REF;
previousTNode = currentTNode = getTNode(elementIndex, lView);
previousTNode = currentTNode = getTNode(tView, elementIndex);
setPreviousOrParentTNode(currentTNode, false);
break;
case I18nMutateOpCode.Attr:
@ -776,7 +776,7 @@ function readCreateOpCodes(
const attrValue = createOpCodes[++i] as string;
// This code is used for ICU expressions only, since we don't support
// directives/components in ICUs, we don't need to worry about inputs here
elementAttributeInternal(elementNodeIndex, attrName, attrValue, lView);
elementAttributeInternal(elementNodeIndex, attrName, attrValue, tView, lView);
break;
default:
throw new Error(`Unable to determine the type of mutate operation for "${opCode}"`);
@ -793,7 +793,7 @@ function readCreateOpCodes(
ngDevMode && ngDevMode.rendererCreateComment++;
previousTNode = currentTNode;
currentTNode = createDynamicNodeAtIndex(
lView, commentNodeIndex, TNodeType.IcuContainer, commentRNode, null);
tView, lView, commentNodeIndex, TNodeType.IcuContainer, commentRNode, null);
visitedNodes.push(commentNodeIndex);
attachPatchData(commentRNode, lView);
(currentTNode as TIcuContainerNode).activeCaseIndex = null;
@ -810,7 +810,7 @@ function readCreateOpCodes(
ngDevMode && ngDevMode.rendererCreateElement++;
previousTNode = currentTNode;
currentTNode = createDynamicNodeAtIndex(
lView, elementNodeIndex, TNodeType.Element, elementRNode, tagNameValue);
tView, lView, elementNodeIndex, TNodeType.Element, elementRNode, tagNameValue);
visitedNodes.push(elementNodeIndex);
break;
default:
@ -826,7 +826,7 @@ function readCreateOpCodes(
function readUpdateOpCodes(
updateOpCodes: I18nUpdateOpCodes, icus: TIcu[] | null, bindingsStartIndex: number,
changeMask: number, viewData: LView, bypassCheckBit = false) {
changeMask: number, tView: TView, lView: LView, bypassCheckBit = false) {
let caseCreated = false;
for (let i = 0; i < updateOpCodes.length; i++) {
// bit code to check if we should apply the next update
@ -843,7 +843,7 @@ function readUpdateOpCodes(
} else if (typeof opCode == 'number') {
if (opCode < 0) {
// It's a binding index whose value is negative
value += renderStringify(viewData[bindingsStartIndex - opCode]);
value += renderStringify(lView[bindingsStartIndex - opCode]);
} else {
const nodeIndex = opCode >>> I18nUpdateOpCode.SHIFT_REF;
let tIcuIndex: number;
@ -853,15 +853,15 @@ function readUpdateOpCodes(
case I18nUpdateOpCode.Attr:
const propName = updateOpCodes[++j] as string;
const sanitizeFn = updateOpCodes[++j] as SanitizerFn | null;
elementPropertyInternal(viewData, nodeIndex, propName, value, sanitizeFn);
elementPropertyInternal(tView, lView, nodeIndex, propName, value, sanitizeFn);
break;
case I18nUpdateOpCode.Text:
textBindingInternal(viewData, nodeIndex, value);
textBindingInternal(lView, nodeIndex, value);
break;
case I18nUpdateOpCode.IcuSwitch:
tIcuIndex = updateOpCodes[++j] as number;
tIcu = icus ![tIcuIndex];
icuTNode = getTNode(nodeIndex, viewData) as TIcuContainerNode;
icuTNode = getTNode(tView, nodeIndex) as TIcuContainerNode;
// If there is an active case, delete the old nodes
if (icuTNode.activeCaseIndex !== null) {
const removeCodes = tIcu.remove[icuTNode.activeCaseIndex];
@ -873,13 +873,13 @@ function readUpdateOpCodes(
// Remove DOM element, but do *not* mark TNode as detached, since we are
// just switching ICU cases (while keeping the same TNode), so a DOM element
// representing a new ICU case will be re-created.
removeNode(nodeIndex, viewData, /* markAsDetached */ false);
removeNode(tView, lView, nodeIndex, /* markAsDetached */ false);
break;
case I18nMutateOpCode.RemoveNestedIcu:
const nestedIcuNodeIndex =
removeCodes[k + 1] as number >>> I18nMutateOpCode.SHIFT_REF;
const nestedIcuTNode =
getTNode(nestedIcuNodeIndex, viewData) as TIcuContainerNode;
getTNode(tView, nestedIcuNodeIndex) as TIcuContainerNode;
const activeIndex = nestedIcuTNode.activeCaseIndex;
if (activeIndex !== null) {
const nestedIcuTIndex = removeOpCode >>> I18nMutateOpCode.SHIFT_REF;
@ -896,18 +896,18 @@ function readUpdateOpCodes(
icuTNode.activeCaseIndex = caseIndex !== -1 ? caseIndex : null;
if (caseIndex > -1) {
// Add the nodes for the new case
readCreateOpCodes(-1, tIcu.create[caseIndex], viewData);
readCreateOpCodes(-1, tIcu.create[caseIndex], tView, lView);
caseCreated = true;
}
break;
case I18nUpdateOpCode.IcuUpdate:
tIcuIndex = updateOpCodes[++j] as number;
tIcu = icus ![tIcuIndex];
icuTNode = getTNode(nodeIndex, viewData) as TIcuContainerNode;
icuTNode = getTNode(tView, nodeIndex) as TIcuContainerNode;
if (icuTNode.activeCaseIndex !== null) {
readUpdateOpCodes(
tIcu.update[icuTNode.activeCaseIndex], icus, bindingsStartIndex, changeMask,
viewData, caseCreated);
tView, lView, caseCreated);
}
break;
}
@ -919,18 +919,18 @@ function readUpdateOpCodes(
}
}
function removeNode(index: number, viewData: LView, markAsDetached: boolean) {
const removedPhTNode = getTNode(index, viewData);
const removedPhRNode = getNativeByIndex(index, viewData);
function removeNode(tView: TView, lView: LView, index: number, markAsDetached: boolean) {
const removedPhTNode = getTNode(tView, index);
const removedPhRNode = getNativeByIndex(index, lView);
if (removedPhRNode) {
nativeRemoveNode(viewData[RENDERER], removedPhRNode);
nativeRemoveNode(lView[RENDERER], removedPhRNode);
}
const slotValue = load(viewData, index) as RElement | RComment | LContainer;
const slotValue = load(lView, index) as RElement | RComment | LContainer;
if (isLContainer(slotValue)) {
const lContainer = slotValue as LContainer;
if (removedPhTNode.type !== TNodeType.Container) {
nativeRemoveNode(viewData[RENDERER], lContainer[NATIVE]);
nativeRemoveNode(lView[RENDERER], lContainer[NATIVE]);
}
}
@ -982,7 +982,7 @@ export function ɵɵi18n(index: number, message: string, subTemplateIndex?: numb
*/
export function ɵɵi18nAttributes(index: number, values: string[]): void {
const lView = getLView();
const tView = lView[TVIEW];
const tView = getTView();
ngDevMode && assertDefined(tView, `tView should be defined`);
i18nAttributesFirstPass(lView, tView, index, values);
}
@ -1014,16 +1014,16 @@ function i18nAttributesFirstPass(lView: LView, tView: TView, index: number, valu
generateBindingUpdateOpCodes(value, previousElementIndex, attrName), updateOpCodes);
}
} else {
const tNode = getTNode(previousElementIndex, lView);
const tNode = getTNode(tView, previousElementIndex);
// Set attributes for Elements only, for other types (like ElementContainer),
// only set inputs below
if (tNode.type === TNodeType.Element) {
elementAttributeInternal(previousElementIndex, attrName, value, lView);
elementAttributeInternal(previousElementIndex, attrName, value, tView, lView);
}
// Check if that attribute is a directive input
const dataValue = tNode.inputs !== null && tNode.inputs[attrName];
if (dataValue) {
setInputsForProperty(lView, dataValue, attrName, value);
setInputsForProperty(tView, lView, dataValue, attrName, value);
if (ngDevMode) {
const element = getNativeByIndex(previousElementIndex, lView) as RElement | RComment;
setNgReflectProperties(lView, element, tNode.type, dataValue, value);
@ -1071,8 +1071,7 @@ export function ɵɵi18nExp<T>(value: T): typeof ɵɵi18nExp {
*/
export function ɵɵi18nApply(index: number) {
if (shiftsCounter) {
const lView = getLView();
const tView = lView[TVIEW];
const tView = getTView();
ngDevMode && assertDefined(tView, `tView should be defined`);
const tI18n = tView.data[index + HEADER_OFFSET];
let updateOpCodes: I18nUpdateOpCodes;
@ -1084,7 +1083,8 @@ export function ɵɵi18nApply(index: number) {
icus = (tI18n as TI18n).icus;
}
const bindingsStartIndex = getBindingIndex() - shiftsCounter - 1;
readUpdateOpCodes(updateOpCodes, icus, bindingsStartIndex, changeMask, lView);
const lView = getLView();
readUpdateOpCodes(updateOpCodes, icus, bindingsStartIndex, changeMask, tView, lView);
// Reset changeMask & maskBit to default for the next update cycle
changeMask = 0b0;

View File

@ -7,9 +7,8 @@
*/
import {assertDataInRange, assertGreaterThan} from '../../util/assert';
import {executeCheckHooks, executeInitAndCheckHooks} from '../hooks';
import {FLAGS, HEADER_OFFSET, InitPhaseState, LView, LViewFlags, TVIEW} from '../interfaces/view';
import {getCheckNoChangesMode, getLView, getSelectedIndex, setSelectedIndex} from '../state';
import {FLAGS, HEADER_OFFSET, InitPhaseState, LView, LViewFlags, TView} from '../interfaces/view';
import {getCheckNoChangesMode, getLView, getSelectedIndex, getTView, setSelectedIndex} from '../state';
/**
@ -37,7 +36,7 @@ import {getCheckNoChangesMode, getLView, getSelectedIndex, setSelectedIndex} fro
*/
export function ɵɵadvance(delta: number): void {
ngDevMode && assertGreaterThan(delta, 0, 'Can only advance forward');
selectIndexInternal(getLView(), getSelectedIndex() + delta, getCheckNoChangesMode());
selectIndexInternal(getTView(), getLView(), getSelectedIndex() + delta, getCheckNoChangesMode());
}
/**
@ -47,10 +46,11 @@ export function ɵɵadvance(delta: number): void {
*/
export function ɵɵselect(index: number): void {
// TODO(misko): Remove this function as it is no longer being used.
selectIndexInternal(getLView(), index, getCheckNoChangesMode());
selectIndexInternal(getTView(), getLView(), index, getCheckNoChangesMode());
}
export function selectIndexInternal(lView: LView, index: number, checkNoChangesMode: boolean) {
export function selectIndexInternal(
tView: TView, lView: LView, index: number, checkNoChangesMode: boolean) {
ngDevMode && assertGreaterThan(index, -1, 'Invalid index');
ngDevMode && assertDataInRange(lView, index + HEADER_OFFSET);
@ -60,12 +60,12 @@ export function selectIndexInternal(lView: LView, index: number, checkNoChangesM
const hooksInitPhaseCompleted =
(lView[FLAGS] & LViewFlags.InitPhaseStateMask) === InitPhaseState.InitPhaseCompleted;
if (hooksInitPhaseCompleted) {
const preOrderCheckHooks = lView[TVIEW].preOrderCheckHooks;
const preOrderCheckHooks = tView.preOrderCheckHooks;
if (preOrderCheckHooks !== null) {
executeCheckHooks(lView, preOrderCheckHooks, index);
}
} else {
const preOrderHooks = lView[TVIEW].preOrderHooks;
const preOrderHooks = tView.preOrderHooks;
if (preOrderHooks !== null) {
executeInitAndCheckHooks(lView, preOrderHooks, InitPhaseState.OnInitHooksToBeRun, index);
}

View File

@ -7,9 +7,7 @@
*/
import {bindingUpdated} from '../bindings';
import {SanitizerFn} from '../interfaces/sanitization';
import {TVIEW} from '../interfaces/view';
import {getLView, getSelectedIndex, nextBindingIndex} from '../state';
import {getLView, getSelectedIndex, getTView, nextBindingIndex} from '../state';
import {elementAttributeInternal, storePropertyBindingMetadata} from './shared';
@ -34,9 +32,9 @@ export function ɵɵattribute(
const bindingIndex = nextBindingIndex();
if (bindingUpdated(lView, bindingIndex, value)) {
const nodeIndex = getSelectedIndex();
elementAttributeInternal(nodeIndex, name, value, lView, sanitizer, namespace);
ngDevMode &&
storePropertyBindingMetadata(lView[TVIEW].data, nodeIndex, 'attr.' + name, bindingIndex);
const tView = getTView();
elementAttributeInternal(nodeIndex, name, value, tView, lView, sanitizer, namespace);
ngDevMode && storePropertyBindingMetadata(tView.data, nodeIndex, 'attr.' + name, bindingIndex);
}
return ɵɵattribute;
}

View File

@ -6,10 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/
import {SanitizerFn} from '../interfaces/sanitization';
import {TVIEW} from '../interfaces/view';
import {getBindingIndex, getLView, getSelectedIndex} from '../state';
import {getBindingIndex, getLView, getSelectedIndex, getTView} from '../state';
import {NO_CHANGE} from '../tokens';
import {interpolation1, interpolation2, interpolation3, interpolation4, interpolation5, interpolation6, interpolation7, interpolation8, interpolationV} from './interpolation';
import {elementAttributeInternal, storePropertyBindingMetadata} from './shared';
@ -46,10 +44,12 @@ export function ɵɵattributeInterpolate1(
const interpolatedValue = interpolation1(lView, prefix, v0, suffix);
if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex();
elementAttributeInternal(nodeIndex, attrName, interpolatedValue, lView, sanitizer, namespace);
ngDevMode && storePropertyBindingMetadata(
lView[TVIEW].data, nodeIndex, 'attr.' + attrName, getBindingIndex() - 1,
prefix, suffix);
const tView = getTView();
elementAttributeInternal(
nodeIndex, attrName, interpolatedValue, tView, lView, sanitizer, namespace);
ngDevMode &&
storePropertyBindingMetadata(
tView.data, nodeIndex, 'attr.' + attrName, getBindingIndex() - 1, prefix, suffix);
}
return ɵɵattributeInterpolate1;
}
@ -87,10 +87,12 @@ export function ɵɵattributeInterpolate2(
const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);
if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex();
elementAttributeInternal(nodeIndex, attrName, interpolatedValue, lView, sanitizer, namespace);
ngDevMode && storePropertyBindingMetadata(
lView[TVIEW].data, nodeIndex, 'attr.' + attrName, getBindingIndex() - 2,
prefix, i0, suffix);
const tView = getTView();
elementAttributeInternal(
nodeIndex, attrName, interpolatedValue, tView, lView, sanitizer, namespace);
ngDevMode &&
storePropertyBindingMetadata(
tView.data, nodeIndex, 'attr.' + attrName, getBindingIndex() - 2, prefix, i0, suffix);
}
return ɵɵattributeInterpolate2;
}
@ -131,10 +133,12 @@ export function ɵɵattributeInterpolate3(
const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);
if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex();
elementAttributeInternal(nodeIndex, attrName, interpolatedValue, lView, sanitizer, namespace);
const tView = getTView();
elementAttributeInternal(
nodeIndex, attrName, interpolatedValue, tView, lView, sanitizer, namespace);
ngDevMode && storePropertyBindingMetadata(
lView[TVIEW].data, nodeIndex, 'attr.' + attrName, getBindingIndex() - 3,
prefix, i0, i1, suffix);
tView.data, nodeIndex, 'attr.' + attrName, getBindingIndex() - 3, prefix, i0,
i1, suffix);
}
return ɵɵattributeInterpolate3;
}
@ -178,10 +182,12 @@ export function ɵɵattributeInterpolate4(
const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);
if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex();
elementAttributeInternal(nodeIndex, attrName, interpolatedValue, lView, sanitizer, namespace);
const tView = getTView();
elementAttributeInternal(
nodeIndex, attrName, interpolatedValue, tView, lView, sanitizer, namespace);
ngDevMode && storePropertyBindingMetadata(
lView[TVIEW].data, nodeIndex, 'attr.' + attrName, getBindingIndex() - 4,
prefix, i0, i1, i2, suffix);
tView.data, nodeIndex, 'attr.' + attrName, getBindingIndex() - 4, prefix, i0,
i1, i2, suffix);
}
return ɵɵattributeInterpolate4;
}
@ -228,10 +234,12 @@ export function ɵɵattributeInterpolate5(
interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);
if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex();
elementAttributeInternal(nodeIndex, attrName, interpolatedValue, lView, sanitizer, namespace);
const tView = getTView();
elementAttributeInternal(
nodeIndex, attrName, interpolatedValue, tView, lView, sanitizer, namespace);
ngDevMode && storePropertyBindingMetadata(
lView[TVIEW].data, nodeIndex, 'attr.' + attrName, getBindingIndex() - 5,
prefix, i0, i1, i2, i3, suffix);
tView.data, nodeIndex, 'attr.' + attrName, getBindingIndex() - 5, prefix, i0,
i1, i2, i3, suffix);
}
return ɵɵattributeInterpolate5;
}
@ -280,10 +288,12 @@ export function ɵɵattributeInterpolate6(
interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);
if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex();
elementAttributeInternal(nodeIndex, attrName, interpolatedValue, lView, sanitizer, namespace);
const tView = getTView();
elementAttributeInternal(
nodeIndex, attrName, interpolatedValue, tView, lView, sanitizer, namespace);
ngDevMode && storePropertyBindingMetadata(
lView[TVIEW].data, nodeIndex, 'attr.' + attrName, getBindingIndex() - 6,
prefix, i0, i1, i2, i3, i4, suffix);
tView.data, nodeIndex, 'attr.' + attrName, getBindingIndex() - 6, prefix, i0,
i1, i2, i3, i4, suffix);
}
return ɵɵattributeInterpolate6;
}
@ -334,10 +344,12 @@ export function ɵɵattributeInterpolate7(
interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);
if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex();
elementAttributeInternal(nodeIndex, attrName, interpolatedValue, lView, sanitizer, namespace);
const tView = getTView();
elementAttributeInternal(
nodeIndex, attrName, interpolatedValue, tView, lView, sanitizer, namespace);
ngDevMode && storePropertyBindingMetadata(
lView[TVIEW].data, nodeIndex, 'attr.' + attrName, getBindingIndex() - 7,
prefix, i0, i1, i2, i3, i4, i5, suffix);
tView.data, nodeIndex, 'attr.' + attrName, getBindingIndex() - 7, prefix, i0,
i1, i2, i3, i4, i5, suffix);
}
return ɵɵattributeInterpolate7;
}
@ -390,10 +402,12 @@ export function ɵɵattributeInterpolate8(
lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);
if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex();
elementAttributeInternal(nodeIndex, attrName, interpolatedValue, lView, sanitizer, namespace);
const tView = getTView();
elementAttributeInternal(
nodeIndex, attrName, interpolatedValue, tView, lView, sanitizer, namespace);
ngDevMode && storePropertyBindingMetadata(
lView[TVIEW].data, nodeIndex, 'attr.' + attrName, getBindingIndex() - 8,
prefix, i0, i1, i2, i3, i4, i5, i6, suffix);
tView.data, nodeIndex, 'attr.' + attrName, getBindingIndex() - 8, prefix, i0,
i1, i2, i3, i4, i5, i6, suffix);
}
return ɵɵattributeInterpolate8;
}
@ -430,15 +444,16 @@ export function ɵɵattributeInterpolateV(
const lView = getLView();
const interpolated = interpolationV(lView, values);
if (interpolated !== NO_CHANGE) {
const tView = getTView();
const nodeIndex = getSelectedIndex();
elementAttributeInternal(nodeIndex, attrName, interpolated, lView, sanitizer, namespace);
elementAttributeInternal(nodeIndex, attrName, interpolated, tView, lView, sanitizer, namespace);
if (ngDevMode) {
const interpolationInBetween = [values[0]]; // prefix
for (let i = 2; i < values.length; i += 2) {
interpolationInBetween.push(values[i]);
}
storePropertyBindingMetadata(
lView[TVIEW].data, nodeIndex, 'attr.' + attrName,
tView.data, nodeIndex, 'attr.' + attrName,
getBindingIndex() - interpolationInBetween.length + 1, ...interpolationInBetween);
}
}

View File

@ -8,7 +8,7 @@
import {assertDefined} from '../../util/assert';
import {getComponentViewByInstance} from '../context_discovery';
import {CONTEXT, RootContext, RootContextFlags} from '../interfaces/view';
import {CONTEXT, RootContext, RootContextFlags, TVIEW} from '../interfaces/view';
import {getRootView} from '../util/view_traversal_utils';
import {detectChangesInternal, markViewDirty, scheduleTick, tickRootContext} from './shared';
@ -21,7 +21,7 @@ import {detectChangesInternal, markViewDirty, scheduleTick, tickRootContext} fro
*/
export function detectChanges(component: {}): void {
const view = getComponentViewByInstance(component);
detectChangesInternal(view, component);
detectChangesInternal(view[TVIEW], view, component);
}
/**

View File

@ -13,12 +13,11 @@ import {ACTIVE_INDEX, CONTAINER_HEADER_OFFSET, LContainer} from '../interfaces/c
import {ComponentTemplate} from '../interfaces/definition';
import {LocalRefExtractor, TAttributes, TContainerNode, TNode, TNodeType, TViewNode} from '../interfaces/node';
import {isDirectiveHost} from '../interfaces/type_checks';
import {FLAGS, HEADER_OFFSET, InitPhaseState, LView, LViewFlags, RENDERER, TVIEW, TView, TViewType, T_HOST} from '../interfaces/view';
import {FLAGS, HEADER_OFFSET, InitPhaseState, LView, LViewFlags, RENDERER, TView, TViewType, T_HOST} from '../interfaces/view';
import {assertNodeType} from '../node_assert';
import {appendChild, removeView} from '../node_manipulation';
import {getBindingIndex, getCheckNoChangesMode, getIsParent, getLView, getPreviousOrParentTNode, setIsNotParent, setPreviousOrParentTNode} from '../state';
import {getBindingIndex, getCheckNoChangesMode, getIsParent, getLView, getPreviousOrParentTNode, getTView, setIsNotParent, setPreviousOrParentTNode} from '../state';
import {getConstant, getLContainerActiveIndex, load} from '../util/view_utils';
import {addToViewTree, createDirectivesInstances, createLContainer, createTNode, createTView, getOrCreateTNode, resolveDirectives, saveResolvedLocalsInData} from './shared';
@ -36,9 +35,10 @@ import {addToViewTree, createDirectivesInstances, createLContainer, createTNode,
*/
export function ɵɵcontainer(index: number): void {
const lView = getLView();
const tNode = containerInternal(lView, index, null, null);
const tView = getTView();
const tNode = containerInternal(tView, lView, index, null, null);
if (lView[TVIEW].firstCreatePass) {
if (tView.firstCreatePass) {
tNode.tViews = [];
}
setIsNotParent();
@ -98,7 +98,7 @@ export function ɵɵtemplate(
tagName?: string | null, attrsIndex?: number | null, localRefsIndex?: number | null,
localRefExtractor?: LocalRefExtractor) {
const lView = getLView();
const tView = lView[TVIEW];
const tView = getTView();
const adjustedIndex = index + HEADER_OFFSET;
const tNode = tView.firstCreatePass ?
@ -108,7 +108,7 @@ export function ɵɵtemplate(
setPreviousOrParentTNode(tNode, false);
const comment = lView[RENDERER].createComment(ngDevMode ? 'container' : '');
appendChild(comment, tNode, lView);
appendChild(tView, lView, comment, tNode);
attachPatchData(comment, lView);
addToViewTree(lView, lView[adjustedIndex] = createLContainer(comment, lView, comment, tNode));
@ -131,7 +131,7 @@ export function ɵɵtemplate(
*/
export function ɵɵcontainerRefreshStart(index: number): void {
const lView = getLView();
const tView = lView[TVIEW];
const tView = getTView();
let previousOrParentTNode = load(tView.data, index) as TNode;
ngDevMode && assertNodeType(previousOrParentTNode, TNodeType.Container);
setPreviousOrParentTNode(previousOrParentTNode, true);
@ -188,10 +188,10 @@ export function ɵɵcontainerRefreshEnd(): void {
}
function containerInternal(
lView: LView, nodeIndex: number, tagName: string | null,
tView: TView, lView: LView, nodeIndex: number, tagName: string | null,
attrs: TAttributes | null): TContainerNode {
ngDevMode && assertEqual(
getBindingIndex(), lView[TVIEW].bindingStartIndex,
getBindingIndex(), tView.bindingStartIndex,
'container nodes should be created before any bindings');
const adjustedIndex = nodeIndex + HEADER_OFFSET;
@ -200,10 +200,10 @@ function containerInternal(
const comment = lView[adjustedIndex] =
lView[RENDERER].createComment(ngDevMode ? 'container' : '');
const tNode =
getOrCreateTNode(lView[TVIEW], lView[T_HOST], nodeIndex, TNodeType.Container, tagName, attrs);
getOrCreateTNode(tView, lView[T_HOST], nodeIndex, TNodeType.Container, tagName, attrs);
const lContainer = lView[adjustedIndex] = createLContainer(comment, lView, comment, tNode);
appendChild(comment, tNode, lView);
appendChild(tView, lView, comment, tNode);
attachPatchData(comment, lView);
// Containers are added to the current view tree instead of their embedded views

View File

@ -16,7 +16,7 @@ import {isContentQueryHost, isDirectiveHost} from '../interfaces/type_checks';
import {HEADER_OFFSET, LView, RENDERER, TVIEW, TView, T_HOST} from '../interfaces/view';
import {assertNodeType} from '../node_assert';
import {appendChild, writeDirectClass, writeDirectStyle} from '../node_manipulation';
import {decreaseElementDepthCount, getBindingIndex, getElementDepthCount, getIsParent, getLView, getNamespace, getPreviousOrParentTNode, increaseElementDepthCount, setIsNotParent, setPreviousOrParentTNode} from '../state';
import {decreaseElementDepthCount, getBindingIndex, getElementDepthCount, getIsParent, getLView, getNamespace, getPreviousOrParentTNode, getTView, increaseElementDepthCount, setIsNotParent, setPreviousOrParentTNode} from '../state';
import {computeStaticStyling} from '../styling/static_styling';
import {setUpAttributes} from '../util/attrs_utils';
import {getConstant} from '../util/view_utils';
@ -36,7 +36,7 @@ function elementStartFirstCreatePass(
const hasDirectives =
resolveDirectives(tView, lView, tNode, getConstant<string[]>(tViewConsts, localRefsIndex));
ngDevMode && warnAboutUnknownElement(lView, native, tNode, hasDirectives);
ngDevMode && warnAboutUnknownElement(tView, lView, native, tNode, hasDirectives);
if (tNode.mergedAttrs !== null) {
computeStaticStyling(tNode, tNode.mergedAttrs);
@ -66,7 +66,7 @@ function elementStartFirstCreatePass(
export function ɵɵelementStart(
index: number, name: string, attrsIndex?: number | null, localRefsIndex?: number): void {
const lView = getLView();
const tView = lView[TVIEW];
const tView = getTView();
const adjustedIndex = HEADER_OFFSET + index;
ngDevMode && assertEqual(
@ -96,7 +96,7 @@ export function ɵɵelementStart(
writeDirectStyle(renderer, native, styles);
}
appendChild(native, tNode, lView);
appendChild(tView, lView, native, tNode);
// any immediate children of a component or template container must be pre-emptively
// monkey-patched with the component view data so that the element can be inspected
@ -135,11 +135,10 @@ export function ɵɵelementEnd(): void {
const tNode = previousOrParentTNode;
ngDevMode && assertNodeType(tNode, TNodeType.Element);
const lView = getLView();
const tView = lView[TVIEW];
decreaseElementDepthCount();
const tView = getTView();
if (tView.firstCreatePass) {
registerPostOrderHooks(tView, previousOrParentTNode);
if (isContentQueryHost(previousOrParentTNode)) {
@ -148,11 +147,11 @@ export function ɵɵelementEnd(): void {
}
if (tNode.classes !== null && hasClassInput(tNode)) {
setDirectiveInputsWhichShadowsStyling(tNode, lView, tNode.classes, true);
setDirectiveInputsWhichShadowsStyling(tView, tNode, getLView(), tNode.classes, true);
}
if (tNode.styles !== null && hasStyleInput(tNode)) {
setDirectiveInputsWhichShadowsStyling(tNode, lView, tNode.styles, false);
setDirectiveInputsWhichShadowsStyling(tView, tNode, getLView(), tNode.styles, false);
}
}
@ -173,8 +172,8 @@ export function ɵɵelement(
}
function warnAboutUnknownElement(
hostView: LView, element: RElement, tNode: TNode, hasDirectives: boolean): void {
const schemas = hostView[TVIEW].schemas;
tView: TView, lView: LView, element: RElement, tNode: TNode, hasDirectives: boolean): void {
const schemas = tView.schemas;
// If `schemas` is set to `null`, that's an indication that this Component was compiled in AOT
// mode where this check happens at compile time. In JIT mode, `schemas` is always present and
@ -197,7 +196,7 @@ function warnAboutUnknownElement(
(typeof customElements !== 'undefined' && tagName.indexOf('-') > -1 &&
!customElements.get(tagName));
if (isUnknown && !matchingSchemas(hostView, tagName)) {
if (isUnknown && !matchingSchemas(tView, lView, tagName)) {
let warning = `'${tagName}' is not a known element:\n`;
warning +=
`1. If '${tagName}' is an Angular component, then verify that it is part of this module.\n`;

View File

@ -11,10 +11,10 @@ import {attachPatchData} from '../context_discovery';
import {registerPostOrderHooks} from '../hooks';
import {TAttributes, TElementContainerNode, TNodeType} from '../interfaces/node';
import {isContentQueryHost, isDirectiveHost} from '../interfaces/type_checks';
import {HEADER_OFFSET, LView, RENDERER, TVIEW, TView, T_HOST} from '../interfaces/view';
import {HEADER_OFFSET, LView, RENDERER, TView, T_HOST} from '../interfaces/view';
import {assertNodeType} from '../node_assert';
import {appendChild} from '../node_manipulation';
import {getBindingIndex, getIsParent, getLView, getPreviousOrParentTNode, setIsNotParent, setPreviousOrParentTNode} from '../state';
import {getBindingIndex, getIsParent, getLView, getPreviousOrParentTNode, getTView, setIsNotParent, setPreviousOrParentTNode} from '../state';
import {computeStaticStyling} from '../styling/static_styling';
import {getConstant} from '../util/view_utils';
@ -63,7 +63,7 @@ function elementContainerStartFirstCreatePass(
export function ɵɵelementContainerStart(
index: number, attrsIndex?: number | null, localRefsIndex?: number): void {
const lView = getLView();
const tView = lView[TVIEW];
const tView = getTView();
const adjustedIndex = index + HEADER_OFFSET;
ngDevMode && assertDataInRange(lView, adjustedIndex);
@ -79,7 +79,7 @@ export function ɵɵelementContainerStart(
ngDevMode && ngDevMode.rendererCreateComment++;
const native = lView[adjustedIndex] =
lView[RENDERER].createComment(ngDevMode ? 'ng-container' : '');
appendChild(native, tNode, lView);
appendChild(tView, lView, native, tNode);
attachPatchData(native, lView);
if (isDirectiveHost(tNode)) {
@ -99,8 +99,7 @@ export function ɵɵelementContainerStart(
*/
export function ɵɵelementContainerEnd(): void {
let previousOrParentTNode = getPreviousOrParentTNode();
const lView = getLView();
const tView = lView[TVIEW];
const tView = getTView();
if (getIsParent()) {
setIsNotParent();
} else {

View File

@ -14,7 +14,7 @@ import {TContainerNode, TNodeType} from '../interfaces/node';
import {CONTEXT, LView, LViewFlags, PARENT, TVIEW, TView, TViewType, T_HOST} from '../interfaces/view';
import {assertNodeType} from '../node_assert';
import {insertView, removeView} from '../node_manipulation';
import {enterView, getIsParent, getLView, getPreviousOrParentTNode, leaveView, setIsParent, setPreviousOrParentTNode} from '../state';
import {enterView, getIsParent, getLView, getPreviousOrParentTNode, getTView, leaveView, setIsParent, setPreviousOrParentTNode} from '../state';
import {getLContainerActiveIndex, isCreationMode} from '../util/view_utils';
import {assignTViewNodeToLView, createLView, createTView, refreshView, renderView} from './shared';
@ -58,7 +58,8 @@ export function ɵɵembeddedViewStart(viewBlockId: number, decls: number, vars:
if (lContainer) {
if (isCreationMode(viewToRender)) {
// it is a new view, insert it into collection of views for a given container
insertView(viewToRender, lContainer, getLContainerActiveIndex(lContainer));
insertView(
viewToRender[TVIEW], viewToRender, lContainer, getLContainerActiveIndex(lContainer));
}
lContainer[ACTIVE_INDEX] += ActiveIndexFlag.INCREMENT;
}
@ -128,14 +129,14 @@ function scanForView(lContainer: LContainer, startIdx: number, viewBlockId: numb
*/
export function ɵɵembeddedViewEnd(): void {
const lView = getLView();
const tView = lView[TVIEW];
const tView = getTView();
const viewHost = lView[T_HOST];
const context = lView[CONTEXT];
if (isCreationMode(lView)) {
renderView(lView, tView, context); // creation mode pass
renderView(tView, lView, context); // creation mode pass
}
refreshView(lView, tView, tView.template, context); // update mode pass
refreshView(tView, lView, tView.template, context); // update mode pass
const lContainer = lView[PARENT] as LContainer;
ngDevMode && assertLContainerOrUndefined(lContainer);

View File

@ -7,10 +7,8 @@
*/
import {bindingUpdated} from '../bindings';
import {SanitizerFn} from '../interfaces/sanitization';
import {TVIEW} from '../interfaces/view';
import {getLView, getSelectedIndex, nextBindingIndex} from '../state';
import {getLView, getSelectedIndex, getTView, nextBindingIndex} from '../state';
import {NO_CHANGE} from '../tokens';
import {elementPropertyInternal, loadComponentRenderer, storePropertyBindingMetadata} from './shared';
/**
@ -33,8 +31,9 @@ export function ɵɵhostProperty<T>(
const bindingIndex = nextBindingIndex();
if (bindingUpdated(lView, bindingIndex, value)) {
const nodeIndex = getSelectedIndex();
elementPropertyInternal(lView, nodeIndex, propName, value, sanitizer, true);
ngDevMode && storePropertyBindingMetadata(lView[TVIEW].data, nodeIndex, propName, bindingIndex);
const tView = getTView();
elementPropertyInternal(tView, lView, nodeIndex, propName, value, sanitizer, true);
ngDevMode && storePropertyBindingMetadata(tView.data, nodeIndex, propName, bindingIndex);
}
return ɵɵhostProperty;
}
@ -68,9 +67,10 @@ export function ɵɵupdateSyntheticHostBinding<T>(
const bindingIndex = nextBindingIndex();
if (bindingUpdated(lView, bindingIndex, value)) {
const nodeIndex = getSelectedIndex();
const tView = getTView();
elementPropertyInternal(
lView, nodeIndex, propName, value, sanitizer, true, loadComponentRenderer);
ngDevMode && storePropertyBindingMetadata(lView[TVIEW].data, nodeIndex, propName, bindingIndex);
tView, lView, nodeIndex, propName, value, sanitizer, true, loadComponentRenderer);
ngDevMode && storePropertyBindingMetadata(tView.data, nodeIndex, propName, bindingIndex);
}
return ɵɵupdateSyntheticHostBinding;
}

View File

@ -13,12 +13,11 @@ import {EMPTY_OBJ} from '../empty';
import {PropertyAliasValue, TNode, TNodeFlags, TNodeType} from '../interfaces/node';
import {GlobalTargetResolver, RElement, Renderer3, isProceduralRenderer} from '../interfaces/renderer';
import {isDirectiveHost} from '../interfaces/type_checks';
import {CLEANUP, FLAGS, LView, LViewFlags, RENDERER, TVIEW} from '../interfaces/view';
import {CLEANUP, FLAGS, LView, LViewFlags, RENDERER, TView} from '../interfaces/view';
import {assertNodeOfPossibleTypes} from '../node_assert';
import {getLView, getPreviousOrParentTNode} from '../state';
import {getLView, getPreviousOrParentTNode, getTView} from '../state';
import {getComponentLViewByIndex, getNativeByTNode, unwrapRNode} from '../util/view_utils';
import {getCleanup, handleError, loadComponentRenderer, markViewDirty} from './shared';
import {getLCleanup, handleError, loadComponentRenderer, markViewDirty} from './shared';
@ -40,9 +39,10 @@ export function ɵɵlistener(
eventName: string, listenerFn: (e?: any) => any, useCapture = false,
eventTargetResolver?: GlobalTargetResolver): typeof ɵɵlistener {
const lView = getLView();
const tView = getTView();
const tNode = getPreviousOrParentTNode();
listenerInternal(
lView, lView[RENDERER], tNode, eventName, listenerFn, useCapture, eventTargetResolver);
tView, lView, lView[RENDERER], tNode, eventName, listenerFn, useCapture, eventTargetResolver);
return ɵɵlistener;
}
@ -70,10 +70,12 @@ export function ɵɵlistener(
export function ɵɵcomponentHostSyntheticListener(
eventName: string, listenerFn: (e?: any) => any, useCapture = false,
eventTargetResolver?: GlobalTargetResolver): typeof ɵɵcomponentHostSyntheticListener {
const lView = getLView();
const tNode = getPreviousOrParentTNode();
const lView = getLView();
const renderer = loadComponentRenderer(tNode, lView);
listenerInternal(lView, renderer, tNode, eventName, listenerFn, useCapture, eventTargetResolver);
const tView = getTView();
listenerInternal(
tView, lView, renderer, tNode, eventName, listenerFn, useCapture, eventTargetResolver);
return ɵɵcomponentHostSyntheticListener;
}
@ -83,8 +85,7 @@ export function ɵɵcomponentHostSyntheticListener(
* are registered for a given element.
*/
function findExistingListener(
lView: LView, eventName: string, tNodeIdx: number): ((e?: any) => any)|null {
const tView = lView[TVIEW];
tView: TView, lView: LView, eventName: string, tNodeIdx: number): ((e?: any) => any)|null {
const tCleanup = tView.cleanup;
if (tCleanup != null) {
for (let i = 0; i < tCleanup.length - 1; i += 2) {
@ -111,10 +112,9 @@ function findExistingListener(
}
function listenerInternal(
lView: LView, renderer: Renderer3, tNode: TNode, eventName: string,
tView: TView, lView: LView, renderer: Renderer3, tNode: TNode, eventName: string,
listenerFn: (e?: any) => any, useCapture = false,
eventTargetResolver?: GlobalTargetResolver): void {
const tView = lView[TVIEW];
const isTNodeDirectiveHost = isDirectiveHost(tNode);
const firstCreatePass = tView.firstCreatePass;
const tCleanup: false|any[] = firstCreatePass && (tView.cleanup || (tView.cleanup = []));
@ -122,7 +122,7 @@ function listenerInternal(
// When the ɵɵlistener instruction was generated and is executed we know that there is either a
// native listener or a directive output on this element. As such we we know that we will have to
// register a listener and store its cleanup function on LView.
const lCleanup = getCleanup(lView);
const lCleanup = getLCleanup(lView);
ngDevMode && assertNodeOfPossibleTypes(
tNode, TNodeType.Element, TNodeType.Container, TNodeType.ElementContainer);
@ -160,7 +160,7 @@ function listenerInternal(
// matching on a given node as we can't register multiple event handlers for the same event in
// a template (this would mean having duplicate attributes).
if (!eventTargetResolver && isTNodeDirectiveHost) {
existingListener = findExistingListener(lView, eventName, tNode.index);
existingListener = findExistingListener(tView, lView, eventName, tNode.index);
}
if (existingListener !== null) {
// Attach a new listener to coalesced listeners list, maintaining the order in which

View File

@ -507,7 +507,7 @@ export function readLViewValue(value: any): LView|null {
export class I18NDebugItem {
[key: string]: any;
get tNode() { return getTNode(this.nodeIndex, this._lView); }
get tNode() { return getTNode(this._lView[TVIEW], this.nodeIndex); }
constructor(
public __raw_opCode: any, private _lView: LView, public nodeIndex: number,

View File

@ -8,10 +8,10 @@
import {newArray} from '../../util/array_utils';
import {TAttributes, TElementNode, TNode, TNodeType} from '../interfaces/node';
import {ProjectionSlots} from '../interfaces/projection';
import {DECLARATION_COMPONENT_VIEW, TVIEW, T_HOST} from '../interfaces/view';
import {DECLARATION_COMPONENT_VIEW, T_HOST} from '../interfaces/view';
import {applyProjection} from '../node_manipulation';
import {getProjectAsAttrValue, isNodeMatchingSelectorList, isSelectorInSelectorList} from '../node_selector_matcher';
import {getLView, setIsNotParent} from '../state';
import {getLView, getTView, setIsNotParent} from '../state';
import {getOrCreateTNode} from './shared';
@ -123,8 +123,9 @@ export function setDelayProjection(value: boolean) {
export function ɵɵprojection(
nodeIndex: number, selectorIndex: number = 0, attrs?: TAttributes): void {
const lView = getLView();
const tProjectionNode = getOrCreateTNode(
lView[TVIEW], lView[T_HOST], nodeIndex, TNodeType.Projection, null, attrs || null);
const tView = getTView();
const tProjectionNode =
getOrCreateTNode(tView, lView[T_HOST], nodeIndex, TNodeType.Projection, null, attrs || null);
// We can't use viewData[HOST_NODE] because projection nodes can be nested in embedded views.
if (tProjectionNode.projection === null) tProjectionNode.projection = selectorIndex;
@ -135,6 +136,6 @@ export function ɵɵprojection(
// We might need to delay the projection of nodes if they are in the middle of an i18n block
if (!delayProjection) {
// re-distribution of projectable nodes is stored on a component's view level
applyProjection(lView, tProjectionNode);
applyProjection(tView, lView, tProjectionNode);
}
}

View File

@ -8,8 +8,8 @@
import {bindingUpdated} from '../bindings';
import {TNode} from '../interfaces/node';
import {SanitizerFn} from '../interfaces/sanitization';
import {LView, TVIEW} from '../interfaces/view';
import {getLView, getSelectedIndex, nextBindingIndex} from '../state';
import {LView, TView} from '../interfaces/view';
import {getLView, getSelectedIndex, getTView, nextBindingIndex} from '../state';
import {elementPropertyInternal, setInputsForProperty, storePropertyBindingMetadata} from './shared';
@ -37,8 +37,9 @@ export function ɵɵproperty<T>(
const bindingIndex = nextBindingIndex();
if (bindingUpdated(lView, bindingIndex, value)) {
const nodeIndex = getSelectedIndex();
elementPropertyInternal(lView, nodeIndex, propName, value, sanitizer);
ngDevMode && storePropertyBindingMetadata(lView[TVIEW].data, nodeIndex, propName, bindingIndex);
const tView = getTView();
elementPropertyInternal(tView, lView, nodeIndex, propName, value, sanitizer);
ngDevMode && storePropertyBindingMetadata(tView.data, nodeIndex, propName, bindingIndex);
}
return ɵɵproperty;
}
@ -48,10 +49,10 @@ export function ɵɵproperty<T>(
* directive input.
*/
export function setDirectiveInputsWhichShadowsStyling(
tNode: TNode, lView: LView, value: any, isClassBased: boolean) {
tView: TView, tNode: TNode, lView: LView, value: any, isClassBased: boolean) {
const inputs = tNode.inputs !;
const property = isClassBased ? 'class' : 'style';
// We support both 'class' and `className` hence the fallback.
const stylingInputs = inputs[property] || (isClassBased && inputs['className']);
setInputsForProperty(lView, stylingInputs, property, value);
setInputsForProperty(tView, lView, stylingInputs, property, value);
}

View File

@ -6,15 +6,12 @@
* found in the LICENSE file at https://angular.io/license
*/
import {SanitizerFn} from '../interfaces/sanitization';
import {TVIEW} from '../interfaces/view';
import {getBindingIndex, getLView, getSelectedIndex} from '../state';
import {getBindingIndex, getLView, getSelectedIndex, getTView} from '../state';
import {NO_CHANGE} from '../tokens';
import {interpolation1, interpolation2, interpolation3, interpolation4, interpolation5, interpolation6, interpolation7, interpolation8, interpolationV} from './interpolation';
import {elementPropertyInternal, storePropertyBindingMetadata} from './shared';
/**
*
* Update an interpolated property on an element with a lone bound value
@ -86,9 +83,10 @@ export function ɵɵpropertyInterpolate1(
const interpolatedValue = interpolation1(lView, prefix, v0, suffix);
if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex();
elementPropertyInternal(lView, nodeIndex, propName, interpolatedValue, sanitizer);
const tView = getTView();
elementPropertyInternal(tView, lView, nodeIndex, propName, interpolatedValue, sanitizer);
ngDevMode && storePropertyBindingMetadata(
lView[TVIEW].data, nodeIndex, propName, getBindingIndex() - 1, prefix, suffix);
tView.data, nodeIndex, propName, getBindingIndex() - 1, prefix, suffix);
}
return ɵɵpropertyInterpolate1;
}
@ -130,10 +128,10 @@ export function ɵɵpropertyInterpolate2(
const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);
if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex();
elementPropertyInternal(lView, nodeIndex, propName, interpolatedValue, sanitizer);
ngDevMode &&
storePropertyBindingMetadata(
lView[TVIEW].data, nodeIndex, propName, getBindingIndex() - 2, prefix, i0, suffix);
const tView = getTView();
elementPropertyInternal(tView, lView, nodeIndex, propName, interpolatedValue, sanitizer);
ngDevMode && storePropertyBindingMetadata(
tView.data, nodeIndex, propName, getBindingIndex() - 2, prefix, i0, suffix);
}
return ɵɵpropertyInterpolate2;
}
@ -178,10 +176,11 @@ export function ɵɵpropertyInterpolate3(
const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);
if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex();
elementPropertyInternal(lView, nodeIndex, propName, interpolatedValue, sanitizer);
const tView = getTView();
elementPropertyInternal(tView, lView, nodeIndex, propName, interpolatedValue, sanitizer);
ngDevMode &&
storePropertyBindingMetadata(
lView[TVIEW].data, nodeIndex, propName, getBindingIndex() - 3, prefix, i0, i1, suffix);
tView.data, nodeIndex, propName, getBindingIndex() - 3, prefix, i0, i1, suffix);
}
return ɵɵpropertyInterpolate3;
}
@ -228,10 +227,11 @@ export function ɵɵpropertyInterpolate4(
const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);
if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex();
elementPropertyInternal(lView, nodeIndex, propName, interpolatedValue, sanitizer);
ngDevMode && storePropertyBindingMetadata(
lView[TVIEW].data, nodeIndex, propName, getBindingIndex() - 4, prefix, i0, i1,
i2, suffix);
const tView = getTView();
elementPropertyInternal(tView, lView, nodeIndex, propName, interpolatedValue, sanitizer);
ngDevMode &&
storePropertyBindingMetadata(
tView.data, nodeIndex, propName, getBindingIndex() - 4, prefix, i0, i1, i2, suffix);
}
return ɵɵpropertyInterpolate4;
}
@ -282,10 +282,11 @@ export function ɵɵpropertyInterpolate5(
interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);
if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex();
elementPropertyInternal(lView, nodeIndex, propName, interpolatedValue, sanitizer);
ngDevMode && storePropertyBindingMetadata(
lView[TVIEW].data, nodeIndex, propName, getBindingIndex() - 5, prefix, i0, i1,
i2, i3, suffix);
const tView = getTView();
elementPropertyInternal(tView, lView, nodeIndex, propName, interpolatedValue, sanitizer);
ngDevMode &&
storePropertyBindingMetadata(
tView.data, nodeIndex, propName, getBindingIndex() - 5, prefix, i0, i1, i2, i3, suffix);
}
return ɵɵpropertyInterpolate5;
}
@ -338,10 +339,11 @@ export function ɵɵpropertyInterpolate6(
interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);
if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex();
elementPropertyInternal(lView, nodeIndex, propName, interpolatedValue, sanitizer);
const tView = getTView();
elementPropertyInternal(tView, lView, nodeIndex, propName, interpolatedValue, sanitizer);
ngDevMode && storePropertyBindingMetadata(
lView[TVIEW].data, nodeIndex, propName, getBindingIndex() - 6, prefix, i0, i1,
i2, i3, i4, suffix);
tView.data, nodeIndex, propName, getBindingIndex() - 6, prefix, i0, i1, i2, i3,
i4, suffix);
}
return ɵɵpropertyInterpolate6;
}
@ -396,10 +398,11 @@ export function ɵɵpropertyInterpolate7(
interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);
if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex();
elementPropertyInternal(lView, nodeIndex, propName, interpolatedValue, sanitizer);
const tView = getTView();
elementPropertyInternal(tView, lView, nodeIndex, propName, interpolatedValue, sanitizer);
ngDevMode && storePropertyBindingMetadata(
lView[TVIEW].data, nodeIndex, propName, getBindingIndex() - 7, prefix, i0, i1,
i2, i3, i4, i5, suffix);
tView.data, nodeIndex, propName, getBindingIndex() - 7, prefix, i0, i1, i2, i3,
i4, i5, suffix);
}
return ɵɵpropertyInterpolate7;
}
@ -456,10 +459,11 @@ export function ɵɵpropertyInterpolate8(
lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);
if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex();
elementPropertyInternal(lView, nodeIndex, propName, interpolatedValue, sanitizer);
const tView = getTView();
elementPropertyInternal(tView, lView, nodeIndex, propName, interpolatedValue, sanitizer);
ngDevMode && storePropertyBindingMetadata(
lView[TVIEW].data, nodeIndex, propName, getBindingIndex() - 8, prefix, i0, i1,
i2, i3, i4, i5, i6, suffix);
tView.data, nodeIndex, propName, getBindingIndex() - 8, prefix, i0, i1, i2, i3,
i4, i5, i6, suffix);
}
return ɵɵpropertyInterpolate8;
}
@ -500,15 +504,16 @@ export function ɵɵpropertyInterpolateV(
const interpolatedValue = interpolationV(lView, values);
if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex();
elementPropertyInternal(lView, nodeIndex, propName, interpolatedValue, sanitizer);
const tView = getTView();
elementPropertyInternal(tView, lView, nodeIndex, propName, interpolatedValue, sanitizer);
if (ngDevMode) {
const interpolationInBetween = [values[0]]; // prefix
for (let i = 2; i < values.length; i += 2) {
interpolationInBetween.push(values[i]);
}
storePropertyBindingMetadata(
lView[TVIEW].data, nodeIndex, propName,
getBindingIndex() - interpolationInBetween.length + 1, ...interpolationInBetween);
tView.data, nodeIndex, propName, getBindingIndex() - interpolationInBetween.length + 1,
...interpolationInBetween);
}
}
return ɵɵpropertyInterpolateV;

View File

@ -31,7 +31,7 @@ import {isComponentDef, isComponentHost, isContentQueryHost, isLContainer, isRoo
import {CHILD_HEAD, CHILD_TAIL, CLEANUP, CONTEXT, DECLARATION_COMPONENT_VIEW, DECLARATION_VIEW, FLAGS, HEADER_OFFSET, HOST, INJECTOR, InitPhaseState, LView, LViewFlags, NEXT, PARENT, RENDERER, RENDERER_FACTORY, RootContext, RootContextFlags, SANITIZER, TData, TVIEW, TView, TViewType, T_HOST} from '../interfaces/view';
import {assertNodeOfPossibleTypes} from '../node_assert';
import {isNodeMatchingSelectorList} from '../node_selector_matcher';
import {enterView, getBindingsEnabled, getCheckNoChangesMode, getIsParent, getPreviousOrParentTNode, getSelectedIndex, leaveView, setBindingIndex, setBindingRootForHostBindings, setCheckNoChangesMode, setCurrentQueryIndex, setPreviousOrParentTNode, setSelectedIndex} from '../state';
import {enterView, getBindingsEnabled, getCheckNoChangesMode, getIsParent, getPreviousOrParentTNode, getSelectedIndex, getTView, leaveView, setBindingIndex, setBindingRootForHostBindings, setCheckNoChangesMode, setCurrentQueryIndex, setPreviousOrParentTNode, setSelectedIndex} from '../state';
import {NO_CHANGE} from '../tokens';
import {isAnimationProp, mergeHostAttrs} from '../util/attrs_utils';
import {INTERPOLATION_DELIMITER, renderStringify, stringifyForError} from '../util/misc_utils';
@ -289,19 +289,19 @@ export function assignTViewNodeToLView(
* i18nApply() or ComponentFactory.create), we need to adjust the blueprint for future
* template passes.
*
* @param view The LView containing the blueprint to adjust
* @param tView `TView` associated with `LView`
* @param view The `LView` containing the blueprint to adjust
* @param numSlotsToAlloc The number of slots to alloc in the LView, should be >0
*/
export function allocExpando(view: LView, numSlotsToAlloc: number) {
export function allocExpando(tView: TView, lView: LView, numSlotsToAlloc: number) {
ngDevMode && assertGreaterThan(
numSlotsToAlloc, 0, 'The number of slots to alloc should be greater than 0');
if (numSlotsToAlloc > 0) {
const tView = view[TVIEW];
if (tView.firstCreatePass) {
for (let i = 0; i < numSlotsToAlloc; i++) {
tView.blueprint.push(null);
tView.data.push(null);
view.push(null);
lView.push(null);
}
// We should only increment the expando start index if there aren't already directives
@ -329,7 +329,7 @@ export function allocExpando(view: LView, numSlotsToAlloc: number) {
* - updating static queries (if any);
* - creating child components defined in a given view.
*/
export function renderView<T>(lView: LView, tView: TView, context: T): void {
export function renderView<T>(tView: TView, lView: LView, context: T): void {
ngDevMode && assertEqual(isCreationMode(lView), true, 'Should be run in creation mode');
enterView(lView, lView[T_HOST]);
try {
@ -342,7 +342,7 @@ export function renderView<T>(lView: LView, tView: TView, context: T): void {
// defined for the root component views.
const templateFn = tView.template;
if (templateFn !== null) {
executeTemplate(lView, templateFn, RenderFlags.Create, context);
executeTemplate(tView, lView, templateFn, RenderFlags.Create, context);
}
// This needs to be set before children are processed to support recursive components.
@ -389,7 +389,7 @@ export function renderView<T>(lView: LView, tView: TView, context: T): void {
* - refreshing child (embedded and component) views.
*/
export function refreshView<T>(
lView: LView, tView: TView, templateFn: ComponentTemplate<{}>| null, context: T) {
tView: TView, lView: LView, templateFn: ComponentTemplate<{}>| null, context: T) {
ngDevMode && assertEqual(isCreationMode(lView), false, 'Should be run in update mode');
const flags = lView[FLAGS];
if ((flags & LViewFlags.Destroyed) === LViewFlags.Destroyed) return;
@ -400,7 +400,7 @@ export function refreshView<T>(
setBindingIndex(tView.bindingStartIndex);
if (templateFn !== null) {
executeTemplate(lView, templateFn, RenderFlags.Update, context);
executeTemplate(tView, lView, templateFn, RenderFlags.Update, context);
}
const hooksInitPhaseCompleted =
@ -505,19 +505,18 @@ export function refreshView<T>(
}
export function renderComponentOrTemplate<T>(
hostView: LView, templateFn: ComponentTemplate<{}>| null, context: T) {
const rendererFactory = hostView[RENDERER_FACTORY];
tView: TView, lView: LView, templateFn: ComponentTemplate<{}>| null, context: T) {
const rendererFactory = lView[RENDERER_FACTORY];
const normalExecutionPath = !getCheckNoChangesMode();
const creationModeIsActive = isCreationMode(hostView);
const creationModeIsActive = isCreationMode(lView);
try {
if (normalExecutionPath && !creationModeIsActive && rendererFactory.begin) {
rendererFactory.begin();
}
const tView = hostView[TVIEW];
if (creationModeIsActive) {
renderView(hostView, tView, context);
renderView(tView, lView, context);
}
refreshView(hostView, tView, templateFn, context);
refreshView(tView, lView, templateFn, context);
} finally {
if (normalExecutionPath && !creationModeIsActive && rendererFactory.end) {
rendererFactory.end();
@ -526,14 +525,14 @@ export function renderComponentOrTemplate<T>(
}
function executeTemplate<T>(
lView: LView, templateFn: ComponentTemplate<T>, rf: RenderFlags, context: T) {
tView: TView, lView: LView, templateFn: ComponentTemplate<T>, rf: RenderFlags, context: T) {
const prevSelectedIndex = getSelectedIndex();
try {
setSelectedIndex(-1);
if (rf & RenderFlags.Update && lView.length > HEADER_OFFSET) {
// When we're updating, inherently select 0 so we don't
// have to generate that instruction for most update blocks.
selectIndexInternal(lView, 0, getCheckNoChangesMode());
selectIndexInternal(tView, lView, 0, getCheckNoChangesMode());
}
templateFn(rf, context);
} finally {
@ -759,12 +758,13 @@ export function locateHostElement(
* - Cleanup function
* - Index of context we just saved in LView.cleanupInstances
*/
export function storeCleanupWithContext(lView: LView, context: any, cleanupFn: Function): void {
const lCleanup = getCleanup(lView);
export function storeCleanupWithContext(
tView: TView, lView: LView, context: any, cleanupFn: Function): void {
const lCleanup = getLCleanup(lView);
lCleanup.push(context);
if (lView[TVIEW].firstCreatePass) {
getTViewCleanup(lView).push(cleanupFn, lCleanup.length - 1);
if (tView.firstCreatePass) {
getTViewCleanup(tView).push(cleanupFn, lCleanup.length - 1);
}
}
@ -776,11 +776,11 @@ export function storeCleanupWithContext(lView: LView, context: any, cleanupFn: F
*
* On the first template pass, the index of the cleanup function is saved in TView.
*/
export function storeCleanupFn(view: LView, cleanupFn: Function): void {
getCleanup(view).push(cleanupFn);
export function storeCleanupFn(tView: TView, lView: LView, cleanupFn: Function): void {
getLCleanup(lView).push(cleanupFn);
if (view[TVIEW].firstCreatePass) {
getTViewCleanup(view).push(view[CLEANUP] !.length - 1, null);
if (tView.firstCreatePass) {
getTViewCleanup(tView).push(lView[CLEANUP] !.length - 1, null);
}
}
@ -941,16 +941,16 @@ function mapPropName(name: string): string {
}
export function elementPropertyInternal<T>(
lView: LView, index: number, propName: string, value: T, sanitizer?: SanitizerFn | null,
nativeOnly?: boolean,
tView: TView, lView: LView, index: number, propName: string, value: T,
sanitizer?: SanitizerFn | null, nativeOnly?: boolean,
loadRendererFn?: ((tNode: TNode, lView: LView) => Renderer3) | null): void {
ngDevMode && assertNotSame(value, NO_CHANGE as any, 'Incoming value should never be NO_CHANGE.');
const element = getNativeByIndex(index, lView) as RElement | RComment;
const tNode = getTNode(index, lView);
const tNode = getTNode(tView, index);
let inputData = tNode.inputs;
let dataValue: PropertyAliasValue|undefined;
if (!nativeOnly && inputData != null && (dataValue = inputData[propName])) {
setInputsForProperty(lView, dataValue, propName, value);
setInputsForProperty(tView, lView, dataValue, propName, value);
if (isComponentHost(tNode)) markDirtyIfOnPush(lView, index + HEADER_OFFSET);
if (ngDevMode) {
setNgReflectProperties(lView, element, tNode.type, dataValue, value);
@ -960,7 +960,7 @@ export function elementPropertyInternal<T>(
if (ngDevMode) {
validateAgainstEventProperties(propName);
if (!validateProperty(lView, element, propName, tNode)) {
if (!validateProperty(tView, lView, element, propName, tNode)) {
// Return here since we only log warnings for unknown properties.
warnAboutUnknownProperty(propName, tNode);
return;
@ -981,7 +981,7 @@ export function elementPropertyInternal<T>(
} else if (tNode.type === TNodeType.Container) {
// If the node is a container and the property didn't
// match any of the inputs or schemas we should throw.
if (ngDevMode && !matchingSchemas(lView, tNode.tagName)) {
if (ngDevMode && !matchingSchemas(tView, lView, tNode.tagName)) {
warnAboutUnknownProperty(propName, tNode);
}
}
@ -1039,10 +1039,11 @@ export function setNgReflectProperties(
}
function validateProperty(
hostView: LView, element: RElement | RComment, propName: string, tNode: TNode): boolean {
tView: TView, lView: LView, element: RElement | RComment, propName: string,
tNode: TNode): boolean {
// The property is considered valid if the element matches the schema, it exists on the element
// or it is synthetic, and we are in a browser context (web worker nodes should be skipped).
if (matchingSchemas(hostView, tNode.tagName) || propName in element ||
if (matchingSchemas(tView, lView, tNode.tagName) || propName in element ||
isAnimationProp(propName)) {
return true;
}
@ -1052,8 +1053,8 @@ function validateProperty(
return typeof Node === 'undefined' || Node === null || !(element instanceof Node);
}
export function matchingSchemas(hostView: LView, tagName: string | null): boolean {
const schemas = hostView[TVIEW].schemas;
export function matchingSchemas(tView: TView, lView: LView, tagName: string | null): boolean {
const schemas = tView.schemas;
if (schemas !== null) {
for (let i = 0; i < schemas.length; i++) {
@ -1437,8 +1438,8 @@ function addComponentLogic<T>(lView: LView, hostTNode: TElementNode, def: Compon
}
export function elementAttributeInternal(
index: number, name: string, value: any, lView: LView, sanitizer?: SanitizerFn | null,
namespace?: string) {
index: number, name: string, value: any, tView: TView, lView: LView,
sanitizer?: SanitizerFn | null, namespace?: string) {
ngDevMode && assertNotSame(value, NO_CHANGE as any, 'Incoming value should never be NO_CHANGE.');
ngDevMode && validateAgainstEventAttributes(name);
const element = getNativeByIndex(index, lView) as RElement;
@ -1449,7 +1450,7 @@ export function elementAttributeInternal(
element.removeAttribute(name);
} else {
ngDevMode && ngDevMode.rendererSetAttribute++;
const tNode = getTNode(index, lView);
const tNode = getTNode(tView, index);
const strValue =
sanitizer == null ? renderStringify(value) : sanitizer(value, tNode.tagName || '', name);
@ -1592,12 +1593,12 @@ function refreshDynamicEmbeddedViews(lView: LView) {
(activeIndexFlag = viewOrContainer[ACTIVE_INDEX]) >> ActiveIndexFlag.SHIFT ===
ActiveIndexFlag.DYNAMIC_EMBEDDED_VIEWS_ONLY) {
for (let i = CONTAINER_HEADER_OFFSET; i < viewOrContainer.length; i++) {
const embeddedLView = viewOrContainer[i];
const embeddedLView = viewOrContainer[i] as LView;
const embeddedTView = embeddedLView[TVIEW];
ngDevMode && assertDefined(embeddedTView, 'TView must be allocated');
if (viewAttachedToChangeDetector(embeddedLView)) {
refreshView(
embeddedLView, embeddedTView, embeddedTView.template, embeddedLView[CONTEXT] !);
embeddedTView, embeddedLView, embeddedTView.template, embeddedLView[CONTEXT] !);
}
}
if ((activeIndexFlag & ActiveIndexFlag.HAS_TRANSPLANTED_VIEWS) !== 0) {
@ -1646,7 +1647,7 @@ function refreshTransplantedViews(lContainer: LContainer, declaredComponentLView
// point.
const movedTView = movedLView[TVIEW];
ngDevMode && assertDefined(movedTView, 'TView must be allocated');
refreshView(movedLView, movedTView, movedTView.template, movedLView[CONTEXT] !);
refreshView(movedTView, movedLView, movedTView.template, movedLView[CONTEXT] !);
}
}
}
@ -1665,16 +1666,17 @@ function refreshComponent(hostLView: LView, componentHostIdx: number): void {
// Only attached components that are CheckAlways or OnPush and dirty should be refreshed
if (viewAttachedToChangeDetector(componentView) &&
componentView[FLAGS] & (LViewFlags.CheckAlways | LViewFlags.Dirty)) {
const tView = componentView[TVIEW];
refreshView(componentView, tView, tView.template, componentView[CONTEXT]);
const componentTView = componentView[TVIEW];
refreshView(componentTView, componentView, componentTView.template, componentView[CONTEXT]);
}
}
function renderComponent(hostLView: LView, componentHostIdx: number) {
ngDevMode && assertEqual(isCreationMode(hostLView), true, 'Should be run in creation mode');
const componentView = getComponentLViewByIndex(componentHostIdx, hostLView);
syncViewWithBlueprint(componentView);
renderView(componentView, componentView[TVIEW], componentView[CONTEXT]);
const componentTView = componentView[TVIEW];
syncViewWithBlueprint(componentTView, componentView);
renderView(componentTView, componentView, componentView[CONTEXT]);
}
/**
@ -1701,12 +1703,12 @@ function renderComponent(hostLView: LView, componentHostIdx: number) {
* Note that embedded views inside ngFor loops will never be out of sync because these views
* are processed as soon as they are created.
*
* @param componentView The view to sync
* @param tView The `TView` that contains the blueprint for syncing
* @param lView The view to sync
*/
function syncViewWithBlueprint(componentView: LView) {
const componentTView = componentView[TVIEW];
for (let i = componentView.length; i < componentTView.blueprint.length; i++) {
componentView.push(componentTView.blueprint[i]);
function syncViewWithBlueprint(tView: TView, lView: LView) {
for (let i = lView.length; i < tView.blueprint.length; i++) {
lView.push(tView.blueprint[i]);
}
}
@ -1723,12 +1725,9 @@ function syncViewWithBlueprint(componentView: LView) {
*/
export function addToViewTree<T extends LView|LContainer>(lView: LView, lViewOrLContainer: T): T {
// TODO(benlesh/misko): This implementation is incorrect, because it always adds the LContainer
// to
// the end of the queue, which means if the developer retrieves the LContainers from RNodes out
// of
// order, the change detection will run out of order, as the act of retrieving the the
// LContainer
// from the RNode is what adds it to the queue.
// to the end of the queue, which means if the developer retrieves the LContainers from RNodes out
// of order, the change detection will run out of order, as the act of retrieving the the
// LContainer from the RNode is what adds it to the queue.
if (lView[CHILD_HEAD]) {
lView[CHILD_TAIL] ![NEXT] = lViewOrLContainer;
} else {
@ -1812,18 +1811,17 @@ export function tickRootContext(rootContext: RootContext) {
const rootComponent = rootContext.components[i];
const lView = readPatchedLView(rootComponent) !;
const tView = lView[TVIEW];
renderComponentOrTemplate(lView, tView.template, rootComponent);
renderComponentOrTemplate(tView, lView, tView.template, rootComponent);
}
}
export function detectChangesInternal<T>(view: LView, context: T) {
const rendererFactory = view[RENDERER_FACTORY];
export function detectChangesInternal<T>(tView: TView, lView: LView, context: T) {
const rendererFactory = lView[RENDERER_FACTORY];
if (rendererFactory.begin) rendererFactory.begin();
try {
const tView = view[TVIEW];
refreshView(view, tView, tView.template, context);
refreshView(tView, lView, tView.template, context);
} catch (error) {
handleError(view, error);
handleError(lView, error);
throw error;
} finally {
if (rendererFactory.end) rendererFactory.end();
@ -1839,10 +1837,10 @@ export function detectChangesInRootView(lView: LView): void {
tickRootContext(lView[CONTEXT] as RootContext);
}
export function checkNoChangesInternal<T>(view: LView, context: T) {
export function checkNoChangesInternal<T>(tView: TView, view: LView, context: T) {
setCheckNoChangesMode(true);
try {
detectChangesInternal(view, context);
detectChangesInternal(tView, view, context);
} finally {
setCheckNoChangesMode(false);
}
@ -1922,13 +1920,13 @@ export function storePropertyBindingMetadata(
export const CLEAN_PROMISE = _CLEAN_PROMISE;
export function getCleanup(view: LView): any[] {
export function getLCleanup(view: LView): any[] {
// top level variables should not be exported for performance reasons (PERF_NOTES.md)
return view[CLEANUP] || (view[CLEANUP] = ngDevMode ? new LCleanup() : []);
}
function getTViewCleanup(view: LView): any[] {
return view[TVIEW].cleanup || (view[TVIEW].cleanup = ngDevMode ? new TCleanup() : []);
function getTViewCleanup(tView: TView): any[] {
return tView.cleanup || (tView.cleanup = ngDevMode ? new TCleanup() : []);
}
/**
@ -1950,14 +1948,14 @@ export function handleError(lView: LView, error: any): void {
/**
* Set the inputs of directives at the current node to corresponding value.
*
* @param tView The current TView
* @param lView the `LView` which contains the directives.
* @param inputs mapping between the public "input" name and privately-known,
* possibly minified, property names to write to.
* @param value Value to set.
*/
export function setInputsForProperty(
lView: LView, inputs: PropertyAliasValue, publicName: string, value: any): void {
const tView = lView[TVIEW];
tView: TView, lView: LView, inputs: PropertyAliasValue, publicName: string, value: any): void {
for (let i = 0; i < inputs.length;) {
const index = inputs[i++] as number;
const privateName = inputs[i++] as string;

View File

@ -5,14 +5,13 @@
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {HEADER_OFFSET, TVIEW} from '../interfaces/view';
import {getContextLView, getLView} from '../state';
import {HEADER_OFFSET, LView, TView} from '../interfaces/view';
import {getContextLView} from '../state';
import {load} from '../util/view_utils';
/** Store a value in the `data` at a given `index`. */
export function store<T>(index: number, value: T): void {
const lView = getLView();
const tView = lView[TVIEW];
export function store<T>(tView: TView, lView: LView, index: number, value: T): void {
// We don't store any static data for local variables, so the first time
// we see the template, we should store as null to avoid a sparse array
const adjustedIndex = index + HEADER_OFFSET;

View File

@ -20,18 +20,16 @@ import {AttributeMarker, TAttributes, TNode, TNodeFlags, TNodeType} from '../int
import {RElement, Renderer3} from '../interfaces/renderer';
import {SanitizerFn} from '../interfaces/sanitization';
import {TStylingKey, TStylingRange, getTStylingRangeNext, getTStylingRangeNextDuplicate, getTStylingRangePrev, getTStylingRangePrevDuplicate} from '../interfaces/styling';
import {HEADER_OFFSET, LView, RENDERER, TData, TVIEW, TView} from '../interfaces/view';
import {HEADER_OFFSET, LView, RENDERER, TData, TView} from '../interfaces/view';
import {applyStyling} from '../node_manipulation';
import {getCurrentDirectiveIndex, getCurrentStyleSanitizer, getLView, getSelectedIndex, incrementBindingIndex, setCurrentStyleSanitizer} from '../state';
import {getCurrentDirectiveIndex, getCurrentStyleSanitizer, getLView, getSelectedIndex, getTView, incrementBindingIndex, setCurrentStyleSanitizer} from '../state';
import {insertTStylingBinding} from '../styling/style_binding_list';
import {getLastParsedKey, getLastParsedValue, parseClassName, parseClassNameNext, parseStyle, parseStyleNext} from '../styling/styling_parser';
import {NO_CHANGE} from '../tokens';
import {getNativeByIndex} from '../util/view_utils';
import {setDirectiveInputsWhichShadowsStyling} from './property';
/**
* Sets the current style sanitizer function which will then be used
* within all follow-up prop and map-based style binding instructions
@ -195,7 +193,7 @@ export function checkStylingProperty(
prop: string, value: any | NO_CHANGE,
suffixOrSanitizer: SanitizerFn | string | undefined | null, isClassBased: boolean): void {
const lView = getLView();
const tView = lView[TVIEW];
const tView = getTView();
// Styling instructions use 2 slots per binding.
// 1. one for the value / TStylingKey
// 2. one for the intermittent-value / TStylingRange
@ -236,12 +234,12 @@ export function checkStylingMap(
keyValueArraySet: (keyValueArray: KeyValueArray<any>, key: string, value: any) => void,
stringParser: (styleKeyValueArray: KeyValueArray<any>, text: string) => void,
value: any|NO_CHANGE, isClassBased: boolean): void {
const lView = getLView();
const tView = lView[TVIEW];
const tView = getTView();
const bindingIndex = incrementBindingIndex(2);
if (tView.firstUpdatePass) {
stylingFirstUpdatePass(tView, null, bindingIndex, isClassBased);
}
const lView = getLView();
if (value !== NO_CHANGE && bindingUpdated(lView, bindingIndex, value)) {
// `getSelectedIndex()` should be here (rather than in instruction) so that it is guarded by the
// if so as not to read unnecessarily.
@ -271,7 +269,7 @@ export function checkStylingMap(
}
// Given `<div [style] my-dir>` such that `my-dir` has `@Input('style')`.
// This takes over the `[style]` binding. (Same for `[class]`)
setDirectiveInputsWhichShadowsStyling(tNode, lView, value, isClassBased);
setDirectiveInputsWhichShadowsStyling(tView, tNode, lView, value, isClassBased);
} else {
updateStylingMap(
tView, tNode, lView, lView[RENDERER], lView[bindingIndex + 1],

View File

@ -7,10 +7,9 @@
*/
import {assertDataInRange, assertEqual} from '../../util/assert';
import {TElementNode, TNodeType} from '../interfaces/node';
import {HEADER_OFFSET, RENDERER, TVIEW, T_HOST} from '../interfaces/view';
import {HEADER_OFFSET, RENDERER, T_HOST} from '../interfaces/view';
import {appendChild, createTextNode} from '../node_manipulation';
import {getBindingIndex, getLView, setPreviousOrParentTNode} from '../state';
import {getBindingIndex, getLView, getTView, setPreviousOrParentTNode} from '../state';
import {getOrCreateTNode} from './shared';
@ -25,7 +24,7 @@ import {getOrCreateTNode} from './shared';
*/
export function ɵɵtext(index: number, value: string = ''): void {
const lView = getLView();
const tView = lView[TVIEW];
const tView = getTView();
const adjustedIndex = index + HEADER_OFFSET;
ngDevMode && assertEqual(
@ -38,7 +37,7 @@ export function ɵɵtext(index: number, value: string = ''): void {
tView.data[adjustedIndex] as TElementNode;
const textNative = lView[adjustedIndex] = createTextNode(value, lView[RENDERER]);
appendChild(textNative, tNode, lView);
appendChild(tView, lView, textNative, tNode);
// Text nodes are self closing.
setPreviousOrParentTNode(tNode, false);

View File

@ -19,7 +19,7 @@ import {TElementNode, TNode, TNodeFlags, TNodeType, TProjectionNode, TViewNode,
import {unusedValueExportToPlacateAjd as unused3} from './interfaces/projection';
import {ProceduralRenderer3, RElement, RNode, RText, Renderer3, isProceduralRenderer, unusedValueExportToPlacateAjd as unused4} from './interfaces/renderer';
import {isLContainer, isLView} from './interfaces/type_checks';
import {CHILD_HEAD, CLEANUP, DECLARATION_COMPONENT_VIEW, DECLARATION_LCONTAINER, FLAGS, HOST, HookData, LView, LViewFlags, NEXT, PARENT, QUERIES, RENDERER, TVIEW, T_HOST, unusedValueExportToPlacateAjd as unused5} from './interfaces/view';
import {CHILD_HEAD, CLEANUP, DECLARATION_COMPONENT_VIEW, DECLARATION_LCONTAINER, FLAGS, HOST, HookData, LView, LViewFlags, NEXT, PARENT, QUERIES, RENDERER, TVIEW, TView, T_HOST, unusedValueExportToPlacateAjd as unused5} from './interfaces/view';
import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert';
import {getLViewParent} from './util/view_traversal_utils';
import {getNativeByTNode, unwrapRNode} from './util/view_utils';
@ -130,31 +130,34 @@ export function createTextNode(value: string, renderer: Renderer3): RText {
* to propagate deeply into the nested containers to remove all elements in the
* views beneath it.
*
* @param tView The `TView' of the `LView` from which elements should be added or removed
* @param lView The view from which elements should be added or removed
* @param insertMode Whether or not elements should be added (if false, removing)
* @param beforeNode The node before which elements should be added, if insert mode
*/
export function addRemoveViewFromContainer(
lView: LView, insertMode: true, beforeNode: RNode | null): void;
export function addRemoveViewFromContainer(lView: LView, insertMode: false, beforeNode: null): void;
tView: TView, lView: LView, insertMode: true, beforeNode: RNode | null): void;
export function addRemoveViewFromContainer(
lView: LView, insertMode: boolean, beforeNode: RNode | null): void {
const renderParent = getContainerRenderParent(lView[TVIEW].node as TViewNode, lView);
ngDevMode && assertNodeType(lView[TVIEW].node as TNode, TNodeType.View);
tView: TView, lView: LView, insertMode: false, beforeNode: null): void;
export function addRemoveViewFromContainer(
tView: TView, lView: LView, insertMode: boolean, beforeNode: RNode | null): void {
const renderParent = getContainerRenderParent(tView.node as TViewNode, lView);
ngDevMode && assertNodeType(tView.node as TNode, TNodeType.View);
if (renderParent) {
const renderer = lView[RENDERER];
const action = insertMode ? WalkTNodeTreeAction.Insert : WalkTNodeTreeAction.Detach;
applyView(renderer, action, lView, renderParent, beforeNode);
applyView(tView, lView, renderer, action, renderParent, beforeNode);
}
}
/**
* Detach a `LView` from the DOM by detaching its nodes.
*
* @param tView The `TView' of the `LView` to be detached
* @param lView the `LView` to be detached.
*/
export function renderDetachView(lView: LView) {
applyView(lView[RENDERER], WalkTNodeTreeAction.Detach, lView, null, null);
export function renderDetachView(tView: TView, lView: LView) {
applyView(tView, lView, lView[RENDERER], WalkTNodeTreeAction.Detach, null, null);
}
/**
@ -174,7 +177,7 @@ export function destroyViewTree(rootView: LView): void {
// If the view has no children, we can clean it up and return early.
let lViewOrLContainer = rootView[CHILD_HEAD];
if (!lViewOrLContainer) {
return cleanUpView(rootView);
return cleanUpView(rootView[TVIEW], rootView);
}
while (lViewOrLContainer) {
@ -194,10 +197,11 @@ export function destroyViewTree(rootView: LView): void {
// Only clean up view when moving to the side or up, as destroy hooks
// should be called in order from the bottom up.
while (lViewOrLContainer && !lViewOrLContainer ![NEXT] && lViewOrLContainer !== rootView) {
cleanUpView(lViewOrLContainer);
isLView(lViewOrLContainer) && cleanUpView(lViewOrLContainer[TVIEW], lViewOrLContainer);
lViewOrLContainer = getParentState(lViewOrLContainer, rootView);
}
cleanUpView(lViewOrLContainer || rootView);
if (lViewOrLContainer === null) lViewOrLContainer = rootView;
isLView(lViewOrLContainer) && cleanUpView(lViewOrLContainer[TVIEW], lViewOrLContainer);
next = lViewOrLContainer && lViewOrLContainer ![NEXT];
}
lViewOrLContainer = next;
@ -212,11 +216,12 @@ export function destroyViewTree(rootView: LView): void {
* root node of another view (in that case, the view's elements will be added when
* the container's parent view is added later).
*
* @param tView The `TView' of the `LView` to insert
* @param lView The view to insert
* @param lContainer The container into which the view should be inserted
* @param index Which index in the container to insert the child view into
*/
export function insertView(lView: LView, lContainer: LContainer, index: number) {
export function insertView(tView: TView, lView: LView, lContainer: LContainer, index: number) {
ngDevMode && assertLView(lView);
ngDevMode && assertLContainer(lContainer);
const indexInContainer = CONTAINER_HEADER_OFFSET + index;
@ -245,7 +250,7 @@ export function insertView(lView: LView, lContainer: LContainer, index: number)
// notify query that a new view has been added
const lQueries = lView[QUERIES];
if (lQueries !== null) {
lQueries.insertView(lView[TVIEW]);
lQueries.insertView(tView);
}
// Sets the attached flag
@ -321,7 +326,7 @@ export function detachView(lContainer: LContainer, removeIndex: number): LView|u
lContainer[indexInContainer - 1][NEXT] = viewToDetach[NEXT] as LView;
}
const removedLView = removeFromArray(lContainer, CONTAINER_HEADER_OFFSET + removeIndex);
addRemoveViewFromContainer(viewToDetach, false, null);
addRemoveViewFromContainer(viewToDetach[TVIEW], viewToDetach, false, null);
// notify query that a view has been removed
const lQueries = removedLView[QUERIES];
@ -345,20 +350,21 @@ export function detachView(lContainer: LContainer, removeIndex: number): LView|u
*/
export function removeView(lContainer: LContainer, removeIndex: number) {
const detachedView = detachView(lContainer, removeIndex);
detachedView && destroyLView(detachedView);
detachedView && destroyLView(detachedView[TVIEW], detachedView);
}
/**
* A standalone function which destroys an LView,
* conducting clean up (e.g. removing listeners, calling onDestroys).
*
* @param tView The `TView' of the `LView` to be destroyed
* @param lView The view to be destroyed.
*/
export function destroyLView(lView: LView) {
export function destroyLView(tView: TView, lView: LView) {
if (!(lView[FLAGS] & LViewFlags.Destroyed)) {
const renderer = lView[RENDERER];
if (isProceduralRenderer(renderer) && renderer.destroyNode) {
applyView(renderer, WalkTNodeTreeAction.Destroy, lView, null, null);
applyView(tView, lView, renderer, WalkTNodeTreeAction.Destroy, null, null);
}
destroyViewTree(lView);
@ -396,50 +402,52 @@ export function getParentState(lViewOrLContainer: LView | LContainer, rootView:
* listeners. Listeners are removed as the last step so events delivered in the onDestroys hooks
* can be propagated to @Output listeners.
*
* @param view The LView to clean up
* @param tView `TView` for the `LView` to clean up.
* @param lView The LView to clean up
*/
function cleanUpView(view: LView | LContainer): void {
if (isLView(view) && !(view[FLAGS] & LViewFlags.Destroyed)) {
function cleanUpView(tView: TView, lView: LView): void {
if (!(lView[FLAGS] & LViewFlags.Destroyed)) {
// Usually the Attached flag is removed when the view is detached from its parent, however
// if it's a root view, the flag won't be unset hence why we're also removing on destroy.
view[FLAGS] &= ~LViewFlags.Attached;
lView[FLAGS] &= ~LViewFlags.Attached;
// Mark the LView as destroyed *before* executing the onDestroy hooks. An onDestroy hook
// runs arbitrary user code, which could include its own `viewRef.destroy()` (or similar). If
// We don't flag the view as destroyed before the hooks, this could lead to an infinite loop.
// This also aligns with the ViewEngine behavior. It also means that the onDestroy hook is
// really more of an "afterDestroy" hook if you think about it.
view[FLAGS] |= LViewFlags.Destroyed;
lView[FLAGS] |= LViewFlags.Destroyed;
executeOnDestroys(view);
removeListeners(view);
const hostTNode = view[T_HOST];
executeOnDestroys(tView, lView);
removeListeners(tView, lView);
const hostTNode = lView[T_HOST];
// For component views only, the local renderer is destroyed as clean up time.
if (hostTNode && hostTNode.type === TNodeType.Element && isProceduralRenderer(view[RENDERER])) {
if (hostTNode && hostTNode.type === TNodeType.Element &&
isProceduralRenderer(lView[RENDERER])) {
ngDevMode && ngDevMode.rendererDestroy++;
(view[RENDERER] as ProceduralRenderer3).destroy();
(lView[RENDERER] as ProceduralRenderer3).destroy();
}
const declarationContainer = view[DECLARATION_LCONTAINER];
const declarationContainer = lView[DECLARATION_LCONTAINER];
// we are dealing with an embedded view that is still inserted into a container
if (declarationContainer !== null && isLContainer(view[PARENT])) {
if (declarationContainer !== null && isLContainer(lView[PARENT])) {
// and this is a projected view
if (declarationContainer !== view[PARENT]) {
detachMovedView(declarationContainer, view);
if (declarationContainer !== lView[PARENT]) {
detachMovedView(declarationContainer, lView);
}
// For embedded views still attached to a container: remove query result from this view.
const lQueries = view[QUERIES];
const lQueries = lView[QUERIES];
if (lQueries !== null) {
lQueries.detachView(view[TVIEW]);
lQueries.detachView(tView);
}
}
}
}
/** Removes listeners and unsubscribes from output subscriptions */
function removeListeners(lView: LView): void {
const tCleanup = lView[TVIEW].cleanup;
function removeListeners(tView: TView, lView: LView): void {
const tCleanup = tView.cleanup;
if (tCleanup !== null) {
const lCleanup = lView[CLEANUP] !;
for (let i = 0; i < tCleanup.length - 1; i += 2) {
@ -475,13 +483,12 @@ function removeListeners(lView: LView): void {
}
/** Calls onDestroy hooks for this view */
function executeOnDestroys(view: LView): void {
const tView = view[TVIEW];
function executeOnDestroys(tView: TView, lView: LView): void {
let destroyHooks: HookData|null;
if (tView != null && (destroyHooks = tView.destroyHooks) != null) {
for (let i = 0; i < destroyHooks.length; i += 2) {
const context = view[destroyHooks[i] as number];
const context = lView[destroyHooks[i] as number];
// Only call the destroy hook if the context has been requested.
if (!(context instanceof NodeInjectorFactory)) {
@ -503,7 +510,7 @@ function executeOnDestroys(view: LView): void {
* of a View which has not be inserted or is made for projection but has not been inserted
* into destination.
*/
function getRenderParent(tNode: TNode, currentView: LView): RElement|null {
function getRenderParent(tView: TView, tNode: TNode, currentView: LView): RElement|null {
// Skip over element and ICU containers as those are represented by a comment node and
// can't be used as a render parent.
let parentTNode = tNode.parent;
@ -542,7 +549,7 @@ function getRenderParent(tNode: TNode, currentView: LView): RElement|null {
ngDevMode && assertNodeType(parentTNode, TNodeType.Element);
if (parentTNode.flags & TNodeFlags.isComponentHost) {
const tData = currentView[TVIEW].data;
const tData = tView.data;
const tNode = tData[parentTNode.index] as TNode;
const encapsulation = (tData[tNode.directiveStart] as ComponentDef<any>).encapsulation;
@ -645,17 +652,19 @@ function getNativeAnchorNode(parentTNode: TNode, lView: LView): RNode|null {
*
* The element insertion might be delayed {@link canInsertNativeNode}.
*
* @param tView The `TView' to be appended
* @param lView The current LView
* @param childEl The native child (or children) that should be appended
* @param childTNode The TNode of the child element
* @param currentView The current LView
* @returns Whether or not the child was appended
*/
export function appendChild(childEl: RNode | RNode[], childTNode: TNode, currentView: LView): void {
const renderParent = getRenderParent(childTNode, currentView);
export function appendChild(
tView: TView, lView: LView, childEl: RNode | RNode[], childTNode: TNode): void {
const renderParent = getRenderParent(tView, childTNode, lView);
if (renderParent != null) {
const renderer = currentView[RENDERER];
const parentTNode: TNode = childTNode.parent || currentView[T_HOST] !;
const anchorNode = getNativeAnchorNode(parentTNode, currentView);
const renderer = lView[RENDERER];
const parentTNode: TNode = childTNode.parent || lView[T_HOST] !;
const anchorNode = getNativeAnchorNode(parentTNode, lView);
if (Array.isArray(childEl)) {
for (let i = 0; i < childEl.length; i++) {
nativeAppendOrInsertBefore(renderer, renderParent, childEl[i], anchorNode);
@ -796,16 +805,16 @@ function applyNodes(
* As you can see this is a very recursive problem. Yes recursion is not most efficient but the
* code is complicated enough that trying to implemented with recursion becomes unmaintainable.
*
* @param tView The `TView' which needs to be inserted, detached, destroyed
* @param lView The LView which needs to be inserted, detached, destroyed.
* @param renderer Renderer to use
* @param action action to perform (insert, detach, destroy)
* @param lView The LView which needs to be inserted, detached, destroyed.
* @param renderParent parent DOM element for insertion/removal.
* @param beforeNode Before which node the insertions should happen.
*/
function applyView(
renderer: Renderer3, action: WalkTNodeTreeAction, lView: LView, renderParent: RElement | null,
beforeNode: RNode | null) {
const tView = lView[TVIEW];
tView: TView, lView: LView, renderer: Renderer3, action: WalkTNodeTreeAction,
renderParent: RElement | null, beforeNode: RNode | null) {
ngDevMode && assertNodeType(tView.node !, TNodeType.View);
const viewRootTNode: TNode|null = tView.node !.child;
applyNodes(renderer, action, viewRootTNode, lView, renderParent, beforeNode, false);
@ -817,12 +826,13 @@ function applyView(
* Inserting a projection requires us to locate the projected nodes from the parent component. The
* complication is that those nodes themselves could be re-projected from their parent component.
*
* @param lView The LView which needs to be inserted, detached, destroyed.
* @param tView The `TView` of `LView` which needs to be inserted, detached, destroyed
* @param lView The `LView` which needs to be inserted, detached, destroyed.
* @param tProjectionNode node to project
*/
export function applyProjection(lView: LView, tProjectionNode: TProjectionNode) {
export function applyProjection(tView: TView, lView: LView, tProjectionNode: TProjectionNode) {
const renderer = lView[RENDERER];
const renderParent = getRenderParent(tProjectionNode, lView);
const renderParent = getRenderParent(tView, tProjectionNode, lView);
const parentTNode = tProjectionNode.parent || lView[T_HOST] !;
let beforeNode = getNativeAnchorNode(parentTNode, lView);
applyProjectionRecursive(
@ -904,7 +914,7 @@ function applyContainer(
}
for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
const lView = lContainer[i] as LView;
applyView(renderer, action, lView, renderParent, anchor);
applyView(lView[TVIEW], lView, renderer, action, renderParent, anchor);
}
}

View File

@ -14,7 +14,7 @@ import {store} from './instructions/all';
import {PipeDef, PipeDefList} from './interfaces/definition';
import {HEADER_OFFSET, LView, TVIEW} from './interfaces/view';
import {pureFunction1Internal, pureFunction2Internal, pureFunction3Internal, pureFunction4Internal, pureFunctionVInternal} from './pure_function';
import {getBindingIndex, getBindingRoot, getLView} from './state';
import {getBindingIndex, getBindingRoot, getLView, getTView} from './state';
import {NO_CHANGE} from './tokens';
import {load} from './util/view_utils';
@ -30,7 +30,7 @@ import {load} from './util/view_utils';
* @codeGenApi
*/
export function ɵɵpipe(index: number, pipeName: string): any {
const tView = getLView()[TVIEW];
const tView = getTView();
let pipeDef: PipeDef<any>;
const adjustedIndex = index + HEADER_OFFSET;
@ -46,7 +46,7 @@ export function ɵɵpipe(index: number, pipeName: string): any {
const pipeFactory = pipeDef.factory || (pipeDef.factory = getFactoryDef(pipeDef.type, true));
const pipeInstance = pipeFactory();
store(index, pipeInstance);
store(tView, getLView(), index, pipeInstance);
return pipeInstance;
}

View File

@ -27,7 +27,7 @@ import {TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeType, u
import {LQueries, LQuery, TQueries, TQuery, TQueryMetadata, unusedValueExportToPlacateAjd as unused4} from './interfaces/query';
import {DECLARATION_LCONTAINER, LView, PARENT, QUERIES, TVIEW, TView} from './interfaces/view';
import {assertNodeOfPossibleTypes} from './node_assert';
import {getCurrentQueryIndex, getLView, getPreviousOrParentTNode, setCurrentQueryIndex} from './state';
import {getCurrentQueryIndex, getLView, getPreviousOrParentTNode, getTView, setCurrentQueryIndex} from './state';
import {isCreationMode} from './util/view_utils';
import {createContainerRef, createElementRef, createTemplateRef} from './view_engine_compatibility';
@ -308,10 +308,11 @@ function createSpecialToken(lView: LView, tNode: TNode, read: any): any {
* processing once and only once for a given view instance (a set of results for a given view
* doesn't change).
*/
function materializeViewResults<T>(lView: LView, tQuery: TQuery, queryIndex: number): (T | null)[] {
function materializeViewResults<T>(
tView: TView, lView: LView, tQuery: TQuery, queryIndex: number): (T | null)[] {
const lQuery = lView[QUERIES] !.queries ![queryIndex];
if (lQuery.matches === null) {
const tViewData = lView[TVIEW].data;
const tViewData = tView.data;
const tQueryMatches = tQuery.matches !;
const result: T|null[] = [];
for (let i = 0; i < tQueryMatches.length; i += 2) {
@ -337,11 +338,11 @@ function materializeViewResults<T>(lView: LView, tQuery: TQuery, queryIndex: num
* A helper function that collects (already materialized) query results from a tree of views,
* starting with a provided LView.
*/
function collectQueryResults<T>(lView: LView, queryIndex: number, result: T[]): T[] {
const tQuery = lView[TVIEW].queries !.getByIndex(queryIndex);
function collectQueryResults<T>(tView: TView, lView: LView, queryIndex: number, result: T[]): T[] {
const tQuery = tView.queries !.getByIndex(queryIndex);
const tQueryMatches = tQuery.matches;
if (tQueryMatches !== null) {
const lViewResults = materializeViewResults<T>(lView, tQuery, queryIndex);
const lViewResults = materializeViewResults<T>(tView, lView, tQuery, queryIndex);
for (let i = 0; i < tQueryMatches.length; i += 2) {
const tNodeIdx = tQueryMatches[i];
@ -359,7 +360,7 @@ function collectQueryResults<T>(lView: LView, queryIndex: number, result: T[]):
for (let i = CONTAINER_HEADER_OFFSET; i < declarationLContainer.length; i++) {
const embeddedLView = declarationLContainer[i];
if (embeddedLView[DECLARATION_LCONTAINER] === embeddedLView[PARENT]) {
collectQueryResults(embeddedLView, childQueryIndex, result);
collectQueryResults(embeddedLView[TVIEW], embeddedLView, childQueryIndex, result);
}
}
@ -368,7 +369,8 @@ function collectQueryResults<T>(lView: LView, queryIndex: number, result: T[]):
if (declarationLContainer[MOVED_VIEWS] !== null) {
const embeddedLViews = declarationLContainer[MOVED_VIEWS] !;
for (let i = 0; i < embeddedLViews.length; i++) {
collectQueryResults(embeddedLViews[i], childQueryIndex, result);
const embeddedLView = embeddedLViews[i];
collectQueryResults(embeddedLView[TVIEW], embeddedLView, childQueryIndex, result);
}
}
}
@ -388,17 +390,19 @@ function collectQueryResults<T>(lView: LView, queryIndex: number, result: T[]):
*/
export function ɵɵqueryRefresh(queryList: QueryList<any>): boolean {
const lView = getLView();
const tView = getTView();
const queryIndex = getCurrentQueryIndex();
setCurrentQueryIndex(queryIndex + 1);
const tQuery = getTQuery(lView[TVIEW], queryIndex);
const tQuery = getTQuery(tView, queryIndex);
if (queryList.dirty && (isCreationMode(lView) === tQuery.metadata.isStatic)) {
if (tQuery.matches === null) {
queryList.reset([]);
} else {
const result = tQuery.crossesNgTemplate ? collectQueryResults(lView, queryIndex, []) :
materializeViewResults(lView, tQuery, queryIndex);
const result = tQuery.crossesNgTemplate ?
collectQueryResults(tView, lView, queryIndex, []) :
materializeViewResults(tView, lView, tQuery, queryIndex);
queryList.reset(result);
queryList.notifyOnChanges();
}
@ -419,7 +423,7 @@ export function ɵɵqueryRefresh(queryList: QueryList<any>): boolean {
*/
export function ɵɵstaticViewQuery<T>(
predicate: Type<any>| string[], descend: boolean, read?: any): void {
viewQueryInternal(getLView(), predicate, descend, read, true);
viewQueryInternal(getTView(), getLView(), predicate, descend, read, true);
}
/**
@ -432,20 +436,19 @@ export function ɵɵstaticViewQuery<T>(
* @codeGenApi
*/
export function ɵɵviewQuery<T>(predicate: Type<any>| string[], descend: boolean, read?: any): void {
viewQueryInternal(getLView(), predicate, descend, read, false);
viewQueryInternal(getTView(), getLView(), predicate, descend, read, false);
}
function viewQueryInternal<T>(
lView: LView, predicate: Type<any>| string[], descend: boolean, read: any,
tView: TView, lView: LView, predicate: Type<any>| string[], descend: boolean, read: any,
isStatic: boolean): void {
const tView = lView[TVIEW];
if (tView.firstCreatePass) {
createTQuery(tView, new TQueryMetadata_(predicate, descend, isStatic, read), -1);
if (isStatic) {
tView.staticViewQueries = true;
}
}
createLQuery<T>(lView);
createLQuery<T>(tView, lView);
}
/**
@ -463,7 +466,8 @@ function viewQueryInternal<T>(
export function ɵɵcontentQuery<T>(
directiveIndex: number, predicate: Type<any>| string[], descend: boolean, read?: any): void {
contentQueryInternal(
getLView(), predicate, descend, read, false, getPreviousOrParentTNode(), directiveIndex);
getTView(), getLView(), predicate, descend, read, false, getPreviousOrParentTNode(),
directiveIndex);
}
/**
@ -481,13 +485,13 @@ export function ɵɵcontentQuery<T>(
export function ɵɵstaticContentQuery<T>(
directiveIndex: number, predicate: Type<any>| string[], descend: boolean, read?: any): void {
contentQueryInternal(
getLView(), predicate, descend, read, true, getPreviousOrParentTNode(), directiveIndex);
getTView(), getLView(), predicate, descend, read, true, getPreviousOrParentTNode(),
directiveIndex);
}
function contentQueryInternal<T>(
lView: LView, predicate: Type<any>| string[], descend: boolean, read: any, isStatic: boolean,
tNode: TNode, directiveIndex: number): void {
const tView = lView[TVIEW];
tView: TView, lView: LView, predicate: Type<any>| string[], descend: boolean, read: any,
isStatic: boolean, tNode: TNode, directiveIndex: number): void {
if (tView.firstCreatePass) {
createTQuery(tView, new TQueryMetadata_(predicate, descend, isStatic, read), tNode.index);
saveContentQueryAndDirectiveIndex(tView, directiveIndex);
@ -496,7 +500,7 @@ function contentQueryInternal<T>(
}
}
createLQuery<T>(lView);
createLQuery<T>(tView, lView);
}
/**
@ -515,9 +519,9 @@ function loadQueryInternal<T>(lView: LView, queryIndex: number): QueryList<T> {
return lView[QUERIES] !.queries[queryIndex].queryList;
}
function createLQuery<T>(lView: LView) {
function createLQuery<T>(tView: TView, lView: LView) {
const queryList = new QueryList<T>();
storeCleanupWithContext(lView, queryList, queryList.destroy);
storeCleanupWithContext(tView, lView, queryList, queryList.destroy);
if (lView[QUERIES] === null) lView[QUERIES] = new LQueries_();
lView[QUERIES] !.queries.push(new LQuery_(queryList));

View File

@ -10,7 +10,7 @@ import {StyleSanitizeFn} from '../sanitization/style_sanitizer';
import {assertDefined} from '../util/assert';
import {assertLViewOrUndefined} from './assert';
import {TNode} from './interfaces/node';
import {CONTEXT, DECLARATION_VIEW, LView, OpaqueViewState, TVIEW} from './interfaces/view';
import {CONTEXT, DECLARATION_VIEW, LView, OpaqueViewState, TVIEW, TView} from './interfaces/view';
/**
@ -39,6 +39,14 @@ interface LFrame {
*/
lView: LView;
/**
* Current `TView` associated with the `LFrame.lView`.
*
* One can get `TView` from `lFrame[TVIEW]` however because it is so common it makes sense to
* store it in `LFrame` for perf reasons.
*/
tView: TView;
/**
* Used to set the parent property when nodes are created and track query results.
*
@ -229,15 +237,17 @@ export function ɵɵdisableBindings(): void {
}
/**
* Return the current LView.
*
* The return value can be `null` if the method is called outside of template. This can happen if
* directive is instantiated by module injector (rather than by node injector.)
* Return the current `LView`.
*/
export function getLView(): LView {
// TODO(misko): the return value should be `LView|null` but doing so breaks a lot of code.
const lFrame = instructionState.lFrame;
return lFrame === null ? null ! : lFrame.lView;
return instructionState.lFrame.lView;
}
/**
* Return the current `TView`.
*/
export function getTView(): TView {
return instructionState.lFrame.tView;
}
/**
@ -293,8 +303,7 @@ export function getBindingRoot() {
const lFrame = instructionState.lFrame;
let index = lFrame.bindingRootIndex;
if (index === -1) {
const lView = lFrame.lView;
index = lFrame.bindingRootIndex = lView[TVIEW].bindingStartIndex;
index = lFrame.bindingRootIndex = lFrame.tView.bindingStartIndex;
}
return index;
}
@ -402,10 +411,12 @@ export const leaveDI = leaveView;
export function enterView(newView: LView, tNode: TNode | null): void {
ngDevMode && assertLViewOrUndefined(newView);
const newLFrame = allocLFrame();
const tView = newView[TVIEW];
instructionState.lFrame = newLFrame;
newLFrame.previousOrParentTNode = tNode !;
newLFrame.isParent = true;
newLFrame.lView = newView;
newLFrame.tView = tView;
newLFrame.selectedIndex = 0;
newLFrame.contextLView = newView !;
newLFrame.elementDepthCount = 0;
@ -413,7 +424,7 @@ export function enterView(newView: LView, tNode: TNode | null): void {
newLFrame.currentNamespace = null;
newLFrame.currentSanitizer = null;
newLFrame.bindingRootIndex = -1;
newLFrame.bindingIndex = newView === null ? -1 : newView[TVIEW].bindingStartIndex;
newLFrame.bindingIndex = tView.bindingStartIndex;
newLFrame.currentQueryIndex = 0;
}
@ -432,6 +443,7 @@ function createLFrame(parent: LFrame | null): LFrame {
previousOrParentTNode: null !, //
isParent: true, //
lView: null !, //
tView: null !, //
selectedIndex: 0, //
contextLView: null !, //
elementDepthCount: 0, //

View File

@ -9,8 +9,7 @@
import {concatStringsWithSpace} from '../../util/stringify';
import {assertFirstCreatePass} from '../assert';
import {AttributeMarker, TAttributes, TNode} from '../interfaces/node';
import {TVIEW} from '../interfaces/view';
import {getLView} from '../state';
import {getTView} from '../state';
/**
* Compute the static styling (class/style) from `TAttributes`.
@ -21,8 +20,8 @@ import {getLView} from '../state';
* @param attrs `TAttributes` containing the styling information.
*/
export function computeStaticStyling(tNode: TNode, attrs: TAttributes): void {
ngDevMode && assertFirstCreatePass(
getLView()[TVIEW], 'Expecting to be called in first template pass only');
ngDevMode &&
assertFirstCreatePass(getTView(), 'Expecting to be called in first template pass only');
let styles: string|null = tNode.styles;
let classes: string|null = tNode.classes;
let mode: AttributeMarker|0 = 0;

View File

@ -11,9 +11,8 @@ import {assertDataInRange, assertEqual, assertNotEqual} from '../../util/assert'
import {assertFirstUpdatePass} from '../assert';
import {TNode} from '../interfaces/node';
import {TStylingKey, TStylingKeyPrimitive, TStylingRange, getTStylingRangeNext, getTStylingRangePrev, setTStylingRangeNext, setTStylingRangeNextDuplicate, setTStylingRangePrev, setTStylingRangePrevDuplicate, toTStylingRange} from '../interfaces/styling';
import {TData, TVIEW} from '../interfaces/view';
import {getLView} from '../state';
import {TData} from '../interfaces/view';
import {getTView} from '../state';
/**
@ -194,7 +193,7 @@ let __unused_const_as_closure_does_not_like_standalone_comment_blocks__: undefin
export function insertTStylingBinding(
tData: TData, tNode: TNode, tStylingKeyWithStatic: TStylingKey, index: number,
isHostBinding: boolean, isClassBinding: boolean): void {
ngDevMode && assertFirstUpdatePass(getLView()[TVIEW]);
ngDevMode && assertFirstUpdatePass(getTView());
let tBindings = isClassBinding ? tNode.classBindings : tNode.styleBindings;
let tmplHead = getTStylingRangePrev(tBindings);
let tmplTail = getTStylingRangeNext(tBindings);

View File

@ -16,7 +16,6 @@ import {DirectiveDef} from '../interfaces/definition';
import {TElementNode, TNode, TNodeProviderIndexes} from '../interfaces/node';
import {isLView} from '../interfaces/type_checks';
import {CLEANUP, CONTEXT, FLAGS, HEADER_OFFSET, HOST, LView, LViewFlags, TVIEW, T_HOST} from '../interfaces/view';
import {stringifyForError} from './misc_utils';
import {getLViewParent, getRootContext} from './view_traversal_utils';
import {getTNode, unwrapRNode} from './view_utils';
@ -388,7 +387,7 @@ export function getDebugNode(element: Element): DebugNode|null {
// this means that value in the lView is a component with its own
// data. In this situation the TNode is not accessed at the same spot.
const tNode = isLView(valueInLView) ? (valueInLView[T_HOST] as TNode) :
getTNode(nodeIndex - HEADER_OFFSET, lView);
getTNode(lView[TVIEW], nodeIndex - HEADER_OFFSET);
debugNode = buildDebugNode(tNode, lView, nodeIndex);
}

View File

@ -13,7 +13,7 @@ import {LContext, MONKEY_PATCH_KEY_NAME} from '../interfaces/context';
import {TConstants, TNode} from '../interfaces/node';
import {RNode, isProceduralRenderer} from '../interfaces/renderer';
import {isLContainer, isLView} from '../interfaces/type_checks';
import {FLAGS, HEADER_OFFSET, HOST, LView, LViewFlags, PARENT, PREORDER_HOOK_FLAGS, RENDERER, TData, TVIEW} from '../interfaces/view';
import {FLAGS, HEADER_OFFSET, HOST, LView, LViewFlags, PARENT, PREORDER_HOOK_FLAGS, RENDERER, TData, TView} from '../interfaces/view';
@ -117,10 +117,10 @@ export function getNativeByTNodeOrNull(tNode: TNode, lView: LView): RNode|null {
}
export function getTNode(index: number, view: LView): TNode {
export function getTNode(tView: TView, index: number): TNode {
ngDevMode && assertGreaterThan(index, -1, 'wrong index for TNode');
ngDevMode && assertLessThan(index, view[TVIEW].data.length, 'wrong index for TNode');
return view[TVIEW].data[index + HEADER_OFFSET] as TNode;
ngDevMode && assertLessThan(index, tView.data.length, 'wrong index for TNode');
return tView.data[index + HEADER_OFFSET] as TNode;
}
/** Retrieves a value from any `LView` or `TData`. */

View File

@ -25,7 +25,7 @@ import {ActiveIndexFlag, CONTAINER_HEADER_OFFSET, LContainer, VIEW_REFS} from '.
import {TContainerNode, TDirectiveHostNode, TElementContainerNode, TElementNode, TNode, TNodeType, TViewNode} from './interfaces/node';
import {RComment, RElement, isProceduralRenderer} from './interfaces/renderer';
import {isComponentHost, isLContainer, isLView, isRootView} from './interfaces/type_checks';
import {DECLARATION_COMPONENT_VIEW, DECLARATION_LCONTAINER, LView, LViewFlags, PARENT, QUERIES, RENDERER, TView, T_HOST} from './interfaces/view';
import {DECLARATION_COMPONENT_VIEW, DECLARATION_LCONTAINER, LView, LViewFlags, PARENT, QUERIES, RENDERER, TVIEW, TView, T_HOST} from './interfaces/view';
import {assertNodeOfPossibleTypes} from './node_assert';
import {addRemoveViewFromContainer, appendChild, detachView, getBeforeNodeForView, insertView, nativeInsertBefore, nativeNextSibling, nativeParentNode, removeView} from './node_manipulation';
import {getParentInjectorTNode} from './node_util';
@ -104,23 +104,23 @@ export function createTemplateRef<T>(
createEmbeddedView(context: T): viewEngine_EmbeddedViewRef<T> {
const embeddedTView = this._declarationTContainer.tViews as TView;
const lView = createLView(
const embeddedLView = createLView(
this._declarationView, embeddedTView, context, LViewFlags.CheckAlways, null,
embeddedTView.node);
const declarationLContainer = this._declarationView[this._declarationTContainer.index];
ngDevMode && assertLContainer(declarationLContainer);
lView[DECLARATION_LCONTAINER] = declarationLContainer;
embeddedLView[DECLARATION_LCONTAINER] = declarationLContainer;
const declarationViewLQueries = this._declarationView[QUERIES];
if (declarationViewLQueries !== null) {
lView[QUERIES] = declarationViewLQueries.createEmbeddedView(embeddedTView);
embeddedLView[QUERIES] = declarationViewLQueries.createEmbeddedView(embeddedTView);
}
renderView(lView, embeddedTView, context);
renderView(embeddedTView, embeddedLView, context);
const viewRef = new ViewRef<T>(lView);
viewRef._tViewNode = lView[T_HOST] as TViewNode;
const viewRef = new ViewRef<T>(embeddedLView);
viewRef._tViewNode = embeddedLView[T_HOST] as TViewNode;
return viewRef;
}
};
@ -238,6 +238,7 @@ export function createContainerRef(
insert(viewRef: viewEngine_ViewRef, index?: number): viewEngine_ViewRef {
const lView = (viewRef as ViewRef<any>)._lView !;
const tView = lView[TVIEW];
if (viewRef.destroyed) {
throw new Error('Cannot insert a destroyed View in a ViewContainer!');
@ -274,10 +275,10 @@ export function createContainerRef(
}
const adjustedIdx = this._adjustIndex(index);
insertView(lView, this._lContainer, adjustedIdx);
insertView(tView, lView, this._lContainer, adjustedIdx);
const beforeNode = getBeforeNodeForView(adjustedIdx, this._lContainer);
addRemoveViewFromContainer(lView, true, beforeNode);
addRemoveViewFromContainer(tView, lView, true, beforeNode);
(viewRef as ViewRef<any>).attachToViewContainerRef(this);
addToArray(this._lContainer[VIEW_REFS] !, adjustedIdx, viewRef);
@ -367,7 +368,7 @@ export function createContainerRef(
nativeInsertBefore(
renderer, parentOfHostNative !, commentNode, nativeNextSibling(renderer, hostNative));
} else {
appendChild(commentNode, hostTNode, hostView);
appendChild(hostView[TVIEW], hostView, commentNode, hostTNode);
}
}

View File

@ -10,12 +10,11 @@ import {ApplicationRef} from '../application_ref';
import {ChangeDetectorRef as viewEngine_ChangeDetectorRef} from '../change_detection/change_detector_ref';
import {ViewContainerRef as viewEngine_ViewContainerRef} from '../linker/view_container_ref';
import {EmbeddedViewRef as viewEngine_EmbeddedViewRef, InternalViewRef as viewEngine_InternalViewRef} from '../linker/view_ref';
import {checkNoChangesInRootView, checkNoChangesInternal, detectChangesInRootView, detectChangesInternal, markViewDirty, storeCleanupFn} from './instructions/shared';
import {CONTAINER_HEADER_OFFSET} from './interfaces/container';
import {TElementNode, TNode, TNodeType, TViewNode} from './interfaces/node';
import {isLContainer} from './interfaces/type_checks';
import {CONTEXT, DECLARATION_COMPONENT_VIEW, FLAGS, HOST, LView, LViewFlags, TVIEW, T_HOST} from './interfaces/view';
import {CONTEXT, DECLARATION_COMPONENT_VIEW, FLAGS, HOST, LView, LViewFlags, TVIEW, TView, T_HOST} from './interfaces/view';
import {assertNodeOfPossibleTypes} from './node_assert';
import {destroyLView, renderDetachView} from './node_manipulation';
import {getLViewParent} from './util/view_traversal_utils';
@ -39,9 +38,10 @@ export class ViewRef<T> implements viewEngine_EmbeddedViewRef<T>, viewEngine_Int
public _tViewNode: TViewNode|null = null;
get rootNodes(): any[] {
if (this._lView[HOST] == null) {
const tView = this._lView[T_HOST] as TViewNode;
return collectNativeNodes(this._lView, tView.child, []);
const lView = this._lView;
if (lView[HOST] == null) {
const hostTView = lView[T_HOST] as TViewNode;
return collectNativeNodes(lView[TVIEW], lView, hostTView.child, []);
}
return [];
}
@ -86,10 +86,10 @@ export class ViewRef<T> implements viewEngine_EmbeddedViewRef<T>, viewEngine_Int
this._viewContainerRef = null;
}
destroyLView(this._lView);
destroyLView(this._lView[TVIEW], this._lView);
}
onDestroy(callback: Function) { storeCleanupFn(this._lView, callback); }
onDestroy(callback: Function) { storeCleanupFn(this._lView[TVIEW], this._lView, callback); }
/**
* Marks a view and all of its ancestors dirty.
@ -261,7 +261,7 @@ export class ViewRef<T> implements viewEngine_EmbeddedViewRef<T>, viewEngine_Int
*
* See {@link ChangeDetectorRef#detach detach} for more information.
*/
detectChanges(): void { detectChangesInternal(this._lView, this.context); }
detectChanges(): void { detectChangesInternal(this._lView[TVIEW], this._lView, this.context); }
/**
* Checks the change detector and its children, and throws if any changes are detected.
@ -269,7 +269,7 @@ export class ViewRef<T> implements viewEngine_EmbeddedViewRef<T>, viewEngine_Int
* This is used in development mode to verify that running change detection doesn't
* introduce other changes.
*/
checkNoChanges(): void { checkNoChangesInternal(this._lView, this.context); }
checkNoChanges(): void { checkNoChangesInternal(this._lView[TVIEW], this._lView, this.context); }
attachToViewContainerRef(vcRef: viewEngine_ViewContainerRef) {
if (this._appRef) {
@ -280,7 +280,7 @@ export class ViewRef<T> implements viewEngine_EmbeddedViewRef<T>, viewEngine_Int
detachFromAppRef() {
this._appRef = null;
renderDetachView(this._lView);
renderDetachView(this._lView[TVIEW], this._lView);
}
attachToAppRef(appRef: ApplicationRef) {
@ -303,7 +303,8 @@ export class RootViewRef<T> extends ViewRef<T> {
}
function collectNativeNodes(
lView: LView, tNode: TNode | null, result: any[], isProjection: boolean = false): any[] {
tView: TView, lView: LView, tNode: TNode | null, result: any[],
isProjection: boolean = false): any[] {
while (tNode !== null) {
ngDevMode && assertNodeOfPossibleTypes(
tNode, TNodeType.Element, TNodeType.Container, TNodeType.Projection,
@ -322,14 +323,15 @@ function collectNativeNodes(
const lViewInAContainer = lNode[i];
const lViewFirstChildTNode = lViewInAContainer[TVIEW].firstChild;
if (lViewFirstChildTNode !== null) {
collectNativeNodes(lViewInAContainer, lViewFirstChildTNode, result);
collectNativeNodes(
lViewInAContainer[TVIEW], lViewInAContainer, lViewFirstChildTNode, result);
}
}
}
const tNodeType = tNode.type;
if (tNodeType === TNodeType.ElementContainer || tNodeType === TNodeType.IcuContainer) {
collectNativeNodes(lView, tNode.child, result);
collectNativeNodes(tView, lView, tNode.child, result);
} else if (tNodeType === TNodeType.Projection) {
const componentView = lView[DECLARATION_COMPONENT_VIEW];
const componentHost = componentView[T_HOST] as TElementNode;
@ -337,7 +339,7 @@ function collectNativeNodes(
let firstProjectedNode: TNode|null =
(componentHost.projection as(TNode | null)[])[tNode.projection as number];
if (firstProjectedNode !== null && parentView !== null) {
collectNativeNodes(parentView, firstProjectedNode, result, true);
collectNativeNodes(parentView[TVIEW], parentView, firstProjectedNode, result, true);
}
}
tNode = isProjection ? tNode.projectionNext : tNode.next;

View File

@ -386,6 +386,9 @@
{
"name": "getSelectedIndex"
},
{
"name": "getTView"
},
{
"name": "growHostVarsSpace"
},

View File

@ -323,6 +323,9 @@
{
"name": "getSelectedIndex"
},
{
"name": "getTView"
},
{
"name": "growHostVarsSpace"
},

View File

@ -566,9 +566,6 @@
{
"name": "getCheckNoChangesMode"
},
{
"name": "getCleanup"
},
{
"name": "getClosureSafeProperty"
},
@ -629,6 +626,9 @@
{
"name": "getIsParent"
},
{
"name": "getLCleanup"
},
{
"name": "getLContainer"
},
@ -725,6 +725,9 @@
{
"name": "getTStylingRangePrevDuplicate"
},
{
"name": "getTView"
},
{
"name": "getTViewCleanup"
},

View File

@ -61,7 +61,7 @@ const updateTime = directiveInputs('update');
console.profile('directive_inputs');
while (updateTime()) {
ctx.counter++;
refreshView(rootLView, rootTView, null, null);
refreshView(rootTView, rootLView, null, null);
}
console.profileEnd();

View File

@ -167,7 +167,7 @@ const refreshTime = duplicateMapBasedStyleAndClassBindingsBenchmark('refresh');
// run change detection in the update mode
console.profile('duplicate_map_based_style_and_class_bindings_refresh');
while (refreshTime()) {
refreshView(rootLView, rootTView, null, null);
refreshView(rootTView, rootLView, null, null);
}
console.profileEnd();

View File

@ -167,7 +167,7 @@ const refreshTime = duplicateStyleAndClassBindingsBenchmark('refresh');
// run change detection in the update mode
console.profile('duplicate_style_and_class_bindings_refresh');
while (refreshTime()) {
refreshView(rootLView, rootTView, null, null);
refreshView(rootTView, rootLView, null, null);
}
console.profileEnd();

View File

@ -99,7 +99,7 @@ const refreshTime = interpolationRefresh('refresh');
// run change detection in the update mode
console.profile('interpolation_refresh');
while (refreshTime()) {
refreshView(rootLView, rootTView, null, null);
refreshView(rootTView, rootLView, null, null);
}
console.profileEnd();

View File

@ -88,7 +88,7 @@ const refreshTime = styleAndClassBindingMapBenchmark('refresh');
// run change detection in the update mode
console.profile('style_and_class_map_binding_refresh');
while (refreshTime()) {
refreshView(rootLView, rootTView, null, null);
refreshView(rootTView, rootLView, null, null);
}
console.profileEnd();

View File

@ -20,7 +20,7 @@ const refreshTime = noopChangeDetection('refresh');
// run change detection in the update mode
console.profile('noop_change_detection');
while (refreshTime()) {
refreshView(rootLView, rootTView, null, null);
refreshView(rootTView, rootLView, null, null);
}
console.profileEnd();

View File

@ -78,7 +78,7 @@ const refreshTime = propertyBindingRefresh('refresh');
// run change detection in the update mode
console.profile('property_binding_refresh');
while (refreshTime()) {
refreshView(rootLView, rootTView, null, null);
refreshView(rootTView, rootLView, null, null);
}
console.profileEnd();

View File

@ -84,7 +84,7 @@ console.profile('element property update');
let i = 0;
while (updateTime()) {
ctx.value = `value${i++}`;
refreshView(rootLView, rootTView, null, ctx);
refreshView(rootTView, rootLView, null, ctx);
}
console.profileEnd();

View File

@ -9,7 +9,7 @@ import {addToViewTree, createLContainer, createLView, createTNode, createTView,
import {ComponentTemplate, DirectiveDefList} from '../../../src/render3/interfaces/definition';
import {TAttributes, TNodeType, TViewNode} from '../../../src/render3/interfaces/node';
import {RendererFactory3, domRendererFactory3} from '../../../src/render3/interfaces/renderer';
import {LView, LViewFlags, TView, TViewType} from '../../../src/render3/interfaces/view';
import {LView, LViewFlags, TVIEW, TView, TViewType} from '../../../src/render3/interfaces/view';
import {insertView} from '../../../src/render3/node_manipulation';
import {MicroBenchmarkRendererFactory} from './noop_renderer';
@ -22,7 +22,7 @@ const renderer = rendererFactory.createRenderer(null, null);
export function createAndRenderLView(parentLView: LView, tView: TView, hostTNode: TViewNode) {
const embeddedLView = createLView(
parentLView, tView, {}, LViewFlags.CheckAlways, null, hostTNode, rendererFactory, renderer);
renderView(embeddedLView, tView, null);
renderView(tView, embeddedLView, null);
}
export function setupRootViewWithEmbeddedViews(
@ -68,17 +68,18 @@ export function setupTestHarness(
const embeddedLView = createLView(
hostLView, embeddedTView, embeddedViewContext, LViewFlags.CheckAlways, null, viewTNode,
rendererFactory, renderer);
renderView(embeddedLView, embeddedTView, embeddedViewContext);
renderView(embeddedTView, embeddedLView, embeddedViewContext);
return embeddedLView;
}
function detectChanges(): void {
refreshView(hostLView, hostTView, hostTView.template, embeddedViewContext);
refreshView(hostTView, hostLView, hostTView.template, embeddedViewContext);
}
// create embedded views and add them to the container
for (let i = 0; i < noOfViews; i++) {
insertView(createEmbeddedLView(), lContainer, i);
const lView = createEmbeddedLView();
insertView(lView[TVIEW], lView, lContainer, i);
}
return {

View File

@ -92,7 +92,7 @@ const refreshTime = styleAndClassBindingBenchmark('refresh');
// run change detection in the update mode
console.profile('style_and_class_binding_refresh');
while (refreshTime()) {
refreshView(rootLView, rootTView, null, null);
refreshView(rootTView, rootLView, null, null);
}
console.profileEnd();

View File

@ -78,7 +78,7 @@ const refreshTime = styleBindingBenchmark('refresh');
// run change detection in the update mode
console.profile('style_binding_refresh');
while (refreshTime()) {
refreshView(rootLView, rootTView, null, null);
refreshView(rootTView, rootLView, null, null);
}
console.profileEnd();

View File

@ -32,7 +32,7 @@ import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveT
import {DirectiveDefList, DirectiveDefListOrFactory, DirectiveTypesOrFactory, HostBindingsFunction, PipeDef, PipeDefList, PipeDefListOrFactory, PipeTypesOrFactory} from '../../src/render3/interfaces/definition';
import {PlayerHandler} from '../../src/render3/interfaces/player';
import {ProceduralRenderer3, RComment, RElement, RNode, RText, Renderer3, RendererFactory3, RendererStyleFlags3, domRendererFactory3} from '../../src/render3/interfaces/renderer';
import {HEADER_OFFSET, LView, LViewFlags, TViewType, T_HOST} from '../../src/render3/interfaces/view';
import {HEADER_OFFSET, LView, LViewFlags, TVIEW, TViewType, T_HOST} from '../../src/render3/interfaces/view';
import {destroyLView} from '../../src/render3/node_manipulation';
import {getRootView} from '../../src/render3/util/view_traversal_utils';
import {Sanitizer} from '../../src/sanitization/sanitizer';
@ -139,7 +139,7 @@ export class TemplateFixture extends BaseFixture {
destroy(): void {
this.containerElement.removeChild(this.hostElement);
destroyLView(this.hostView);
destroyLView(this.hostView[TVIEW], this.hostView);
}
}
@ -190,7 +190,8 @@ export class ComponentFixture<T> extends BaseFixture {
this.containerElement.removeChild(this.hostElement);
}
destroyLView(getRootView(this.component));
const rootLView = getRootView(this.component);
destroyLView(rootLView[TVIEW], rootLView);
}
}
@ -279,7 +280,7 @@ export function renderTemplate<T>(
hostLView, componentTView, context, LViewFlags.CheckAlways, hostNode, hostTNode,
providedRendererFactory, renderer, sanitizer);
}
renderComponentOrTemplate(componentView, templateFn, context);
renderComponentOrTemplate(componentView[TVIEW], componentView, templateFn, context);
return componentView;
}