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-02-04 12:56:47 -08:00
parent 770980de69
commit d528dedd50
47 changed files with 494 additions and 445 deletions
+2 -2
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();
+2 -2
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();
}
+3 -4
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);
File diff suppressed because it is too large Load Diff
@@ -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);
}
@@ -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;
}
@@ -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);
}
}
@@ -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);
}
/**
@@ -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
@@ -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`;
@@ -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 {
@@ -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);
@@ -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;
}
@@ -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
@@ -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,
@@ -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);
}
}
@@ -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);
}
@@ -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;
File diff suppressed because it is too large Load Diff
@@ -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;
@@ -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],
@@ -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);
+66 -56
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 cleanup (e.g. removing listeners, calling onDestroys).
* 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);
}
}
+3 -3
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;
}
+28 -24
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));
+23 -11
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, //
@@ -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;
@@ -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);
@@ -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);
}
+4 -4
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`. */

Some files were not shown because too many files have changed in this diff Show More