parent
dc4a3d00d0
commit
29eb24b142
|
@ -10,19 +10,16 @@
|
|||
// correctly implementing its interfaces for backwards compatibility.
|
||||
import {Type} from '../core';
|
||||
import {Injector} from '../di/injector';
|
||||
import {ComponentRef as viewEngine_ComponentRef} from '../linker/component_factory';
|
||||
import {Sanitizer} from '../sanitization/security';
|
||||
|
||||
import {assertComponentType, assertDefined} from './assert';
|
||||
import {queueInitHooks, queueLifecycleHooks} from './hooks';
|
||||
import {CLEAN_PROMISE, ROOT_DIRECTIVE_INDICES, _getComponentHostLElementNode, baseDirectiveCreate, createLView, createTView, detectChangesInternal, enterView, executeInitAndContentHooks, getRootView, hostElement, initChangeDetectorIfExisting, leaveView, locateHostElement, setHostBindings} from './instructions';
|
||||
import {CLEAN_PROMISE, ROOT_DIRECTIVE_INDICES, _getComponentHostLElementNode, baseDirectiveCreate, createLViewData, createTView, detectChangesInternal, enterView, executeInitAndContentHooks, getRootView, hostElement, initChangeDetectorIfExisting, leaveView, locateHostElement, setHostBindings,} from './instructions';
|
||||
import {ComponentDef, ComponentType} from './interfaces/definition';
|
||||
import {LElementNode, TNodeFlags} from './interfaces/node';
|
||||
import {LElementNode} from './interfaces/node';
|
||||
import {RElement, RendererFactory3, domRendererFactory3} from './interfaces/renderer';
|
||||
import {LView, LViewFlags, RootContext} from './interfaces/view';
|
||||
import {LViewData, LViewFlags, RootContext, INJECTOR, CONTEXT, TVIEW} from './interfaces/view';
|
||||
import {stringify} from './util';
|
||||
import {ViewRef} from './view_ref';
|
||||
|
||||
|
||||
|
||||
/** Options that control how the component should be bootstrapped. */
|
||||
|
@ -71,7 +68,6 @@ export interface CreateComponentOptions {
|
|||
scheduler?: (work: () => void) => void;
|
||||
}
|
||||
|
||||
|
||||
// TODO: A hack to not pull in the NullInjector from @angular/core.
|
||||
export const NULL_INJECTOR: Injector = {
|
||||
get: (token: any, notFoundValue?: any) => {
|
||||
|
@ -108,11 +104,11 @@ export function renderComponent<T>(
|
|||
const hostNode = locateHostElement(rendererFactory, opts.host || componentTag);
|
||||
const rootContext = createRootContext(opts.scheduler || requestAnimationFrame.bind(window));
|
||||
|
||||
const rootView: LView = createLView(
|
||||
const rootView: LViewData = createLViewData(
|
||||
rendererFactory.createRenderer(hostNode, componentDef.rendererType),
|
||||
createTView(-1, null, null, null), rootContext,
|
||||
componentDef.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways);
|
||||
rootView.injector = opts.injector || null;
|
||||
rootView[INJECTOR] = opts.injector || null;
|
||||
|
||||
const oldView = enterView(rootView, null !);
|
||||
let elementNode: LElementNode;
|
||||
|
@ -131,7 +127,7 @@ export function renderComponent<T>(
|
|||
|
||||
executeInitAndContentHooks();
|
||||
setHostBindings(ROOT_DIRECTIVE_INDICES);
|
||||
detectChangesInternal(elementNode.data as LView, elementNode, component);
|
||||
detectChangesInternal(elementNode.data as LViewData, elementNode, component);
|
||||
} finally {
|
||||
leaveView(oldView);
|
||||
if (rendererFactory.end) rendererFactory.end();
|
||||
|
@ -165,8 +161,9 @@ export function LifecycleHooksFeature(component: any, def: ComponentDef<any>): v
|
|||
const elementNode = _getComponentHostLElementNode(component);
|
||||
|
||||
// Root component is always created at dir index 0
|
||||
queueInitHooks(0, def.onInit, def.doCheck, elementNode.view.tView);
|
||||
queueLifecycleHooks(elementNode.tNode.flags, elementNode.view);
|
||||
const tView = elementNode.view[TVIEW];
|
||||
queueInitHooks(0, def.onInit, def.doCheck, tView);
|
||||
queueLifecycleHooks(elementNode.tNode.flags, tView);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -176,7 +173,7 @@ export function LifecycleHooksFeature(component: any, def: ComponentDef<any>): v
|
|||
* @param component any component
|
||||
*/
|
||||
function getRootContext(component: any): RootContext {
|
||||
const rootContext = getRootView(component).context as RootContext;
|
||||
const rootContext = getRootView(component)[CONTEXT] as RootContext;
|
||||
ngDevMode && assertDefined(rootContext, 'rootContext');
|
||||
return rootContext;
|
||||
}
|
||||
|
|
|
@ -18,11 +18,11 @@ import {Type} from '../type';
|
|||
|
||||
import {assertComponentType, assertDefined} from './assert';
|
||||
import {createRootContext} from './component';
|
||||
import {baseDirectiveCreate, createLView, createTView, enterView, hostElement, initChangeDetectorIfExisting, leaveView, locateHostElement} from './instructions';
|
||||
import {baseDirectiveCreate, createLViewData, createTView, enterView, hostElement, initChangeDetectorIfExisting, locateHostElement} from './instructions';
|
||||
import {ComponentDef, ComponentType} from './interfaces/definition';
|
||||
import {LElementNode} from './interfaces/node';
|
||||
import {RElement} from './interfaces/renderer';
|
||||
import {LView, LViewFlags, RootContext} from './interfaces/view';
|
||||
import {INJECTOR, LViewData, LViewFlags, RootContext} from './interfaces/view';
|
||||
import {ViewRef} from './view_ref';
|
||||
|
||||
export class ComponentFactoryResolver extends viewEngine_ComponentFactoryResolver {
|
||||
|
@ -94,11 +94,11 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
|
|||
const rootContext: RootContext = ngModule !.injector.get(ROOT_CONTEXT);
|
||||
|
||||
// Create the root view. Uses empty TView and ContentTemplate.
|
||||
const rootView: LView = createLView(
|
||||
const rootView: LViewData = createLViewData(
|
||||
rendererFactory.createRenderer(hostNode, this.componentDef.rendererType),
|
||||
createTView(-1, null, null, null), null,
|
||||
this.componentDef.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways);
|
||||
rootView.injector = ngModule && ngModule.injector || null;
|
||||
rootView[INJECTOR] = ngModule && ngModule.injector || null;
|
||||
|
||||
// rootView is the parent when bootstrapping
|
||||
const oldView = enterView(rootView, null !);
|
||||
|
@ -145,7 +145,7 @@ export class ComponentRef<T> extends viewEngine_ComponentRef<T> {
|
|||
componentType: Type<T>;
|
||||
|
||||
constructor(
|
||||
componentType: Type<T>, instance: T, rootView: LView, injector: Injector,
|
||||
componentType: Type<T>, instance: T, rootView: LViewData, injector: Injector,
|
||||
hostNode: RElement) {
|
||||
super();
|
||||
this.instance = instance;
|
||||
|
@ -173,4 +173,4 @@ export class ComponentRef<T> extends viewEngine_ComponentRef<T> {
|
|||
ngDevMode && assertDefined(this.destroyCbs, 'NgModule already destroyed');
|
||||
this.destroyCbs !.push(callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,13 +19,14 @@ import {EmbeddedViewRef as viewEngine_EmbeddedViewRef, ViewRef as viewEngine_Vie
|
|||
import {Type} from '../type';
|
||||
|
||||
import {assertDefined, assertGreaterThan, assertLessThan} from './assert';
|
||||
import {addToViewTree, assertPreviousIsParent, createLContainer, createLNodeObject, createTNode, createTView, getDirectiveInstance, getPreviousOrParentNode, getRenderer, isComponent, renderEmbeddedTemplate, resolveDirective} from './instructions';
|
||||
import {ComponentTemplate, DirectiveDef, DirectiveDefList, PipeDefList} from './interfaces/definition';
|
||||
import {addToViewTree, assertPreviousIsParent, createLContainer, createLNodeObject, createTNode, getDirectiveInstance, getPreviousOrParentNode, getRenderer, isComponent, renderEmbeddedTemplate, resolveDirective} from './instructions';
|
||||
import {VIEWS} from './interfaces/container';
|
||||
import {ComponentTemplate, DirectiveDef} from './interfaces/definition';
|
||||
import {LInjector} from './interfaces/injector';
|
||||
import {AttributeMarker, LContainerNode, LElementNode, LNode, LViewNode, TNodeFlags, TNodeType} from './interfaces/node';
|
||||
import {LQueries, QueryReadType} from './interfaces/query';
|
||||
import {Renderer3} from './interfaces/renderer';
|
||||
import {LView, TView} from './interfaces/view';
|
||||
import {DIRECTIVES, HOST_NODE, INJECTOR, LViewData, QUERIES, TVIEW, TView} from './interfaces/view';
|
||||
import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert';
|
||||
import {detachView, getParentLNode, insertView, removeView} from './node_manipulation';
|
||||
import {notImplemented, stringify} from './util';
|
||||
|
@ -282,9 +283,9 @@ export function getOrCreateChangeDetectorRef(
|
|||
|
||||
const currentNode = di.node;
|
||||
if (isComponent(currentNode.tNode)) {
|
||||
return di.changeDetectorRef = new ViewRef(currentNode.data as LView, context);
|
||||
return di.changeDetectorRef = new ViewRef(currentNode.data as LViewData, context);
|
||||
} else if (currentNode.tNode.type === TNodeType.Element) {
|
||||
return di.changeDetectorRef = getOrCreateHostChangeDetector(currentNode.view.node);
|
||||
return di.changeDetectorRef = getOrCreateHostChangeDetector(currentNode.view[HOST_NODE]);
|
||||
}
|
||||
return null !;
|
||||
}
|
||||
|
@ -299,9 +300,9 @@ function getOrCreateHostChangeDetector(currentNode: LViewNode | LElementNode):
|
|||
return existingRef ?
|
||||
existingRef :
|
||||
new ViewRef(
|
||||
hostNode.data as LView,
|
||||
hostNode.view
|
||||
.directives ![hostNode.tNode.flags >> TNodeFlags.DirectiveStartingIndexShift]);
|
||||
hostNode.data as LViewData,
|
||||
hostNode
|
||||
.view[DIRECTIVES] ![hostNode.tNode.flags >> TNodeFlags.DirectiveStartingIndexShift]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -311,7 +312,7 @@ function getOrCreateHostChangeDetector(currentNode: LViewNode | LElementNode):
|
|||
*/
|
||||
function getClosestComponentAncestor(node: LViewNode | LElementNode): LElementNode {
|
||||
while (node.tNode.type === TNodeType.View) {
|
||||
node = node.view.node;
|
||||
node = node.view[HOST_NODE];
|
||||
}
|
||||
return node as LElementNode;
|
||||
}
|
||||
|
@ -340,7 +341,7 @@ export function getOrCreateInjectable<T>(
|
|||
// If the token has a bloom hash, then it is a directive that is public to the injection system
|
||||
// (diPublic). If there is no hash, fall back to the module injector.
|
||||
if (bloomHash === null) {
|
||||
const moduleInjector = getPreviousOrParentNode().view.injector;
|
||||
const moduleInjector = getPreviousOrParentNode().view[INJECTOR];
|
||||
const formerInjector = setCurrentInjector(moduleInjector);
|
||||
try {
|
||||
return inject(token, flags);
|
||||
|
@ -370,14 +371,14 @@ export function getOrCreateInjectable<T>(
|
|||
if (count !== 0) {
|
||||
const start = nodeFlags >> TNodeFlags.DirectiveStartingIndexShift;
|
||||
const end = start + count;
|
||||
const defs = node.view.tView.directives !;
|
||||
const defs = node.view[TVIEW].directives !;
|
||||
|
||||
for (let i = start; i < end; i++) {
|
||||
// Get the definition for the directive at this index and, if it is injectable (diPublic),
|
||||
// and matches the given token, return the directive instance.
|
||||
const directiveDef = defs[i] as DirectiveDef<any>;
|
||||
if (directiveDef.type === token && directiveDef.diPublic) {
|
||||
return getDirectiveInstance(node.view.directives ![i]);
|
||||
return getDirectiveInstance(node.view[DIRECTIVES] ![i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -405,12 +406,12 @@ export function getOrCreateInjectable<T>(
|
|||
}
|
||||
|
||||
function searchMatchesQueuedForCreation<T>(node: LNode, token: any): T|null {
|
||||
const matches = node.view.tView.currentMatches;
|
||||
const matches = node.view[TVIEW].currentMatches;
|
||||
if (matches) {
|
||||
for (let i = 0; i < matches.length; i += 2) {
|
||||
const def = matches[i] as DirectiveDef<any>;
|
||||
if (def.type === token) {
|
||||
return resolveDirective(def, i + 1, matches, node.view.tView);
|
||||
return resolveDirective(def, i + 1, matches, node.view[TVIEW]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -545,7 +546,7 @@ export const QUERY_READ_FROM_NODE =
|
|||
(new ReadFromInjectorFn<any>((injector: LInjector, node: LNode, directiveIdx: number) => {
|
||||
ngDevMode && assertNodeOfPossibleTypes(node, TNodeType.Container, TNodeType.Element);
|
||||
if (directiveIdx > -1) {
|
||||
return node.view.directives ![directiveIdx];
|
||||
return node.view[DIRECTIVES] ![directiveIdx];
|
||||
} else if (node.tNode.type === TNodeType.Element) {
|
||||
return getOrCreateElementRef(injector);
|
||||
} else if (node.tNode.type === TNodeType.Container) {
|
||||
|
@ -611,7 +612,7 @@ class ViewContainerRef implements viewEngine_ViewContainerRef {
|
|||
|
||||
clear(): void {
|
||||
const lContainer = this._lContainerNode.data;
|
||||
while (lContainer.views.length) {
|
||||
while (lContainer[VIEWS].length) {
|
||||
this.remove(0);
|
||||
}
|
||||
}
|
||||
|
@ -620,7 +621,7 @@ class ViewContainerRef implements viewEngine_ViewContainerRef {
|
|||
|
||||
get length(): number {
|
||||
const lContainer = this._lContainerNode.data;
|
||||
return lContainer.views.length;
|
||||
return lContainer[VIEWS].length;
|
||||
}
|
||||
|
||||
createEmbeddedView<C>(templateRef: viewEngine_TemplateRef<C>, context?: C, index?: number):
|
||||
|
@ -679,12 +680,12 @@ class ViewContainerRef implements viewEngine_ViewContainerRef {
|
|||
|
||||
private _adjustIndex(index?: number, shift: number = 0) {
|
||||
if (index == null) {
|
||||
return this._lContainerNode.data.views.length + shift;
|
||||
return this._lContainerNode.data[VIEWS].length + shift;
|
||||
}
|
||||
if (ngDevMode) {
|
||||
assertGreaterThan(index, -1, 'index must be positive');
|
||||
// +1 because it's legal to insert at the end.
|
||||
assertLessThan(index, this._lContainerNode.data.views.length + 1 + shift, 'index');
|
||||
assertLessThan(index, this._lContainerNode.data[VIEWS].length + 1 + shift, 'index');
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
@ -704,7 +705,8 @@ export function getOrCreateTemplateRef<T>(di: LInjector): viewEngine_TemplateRef
|
|||
const hostTNode = hostNode.tNode;
|
||||
ngDevMode && assertDefined(hostTNode.tViews, 'TView must be allocated');
|
||||
di.templateRef = new TemplateRef<any>(
|
||||
getOrCreateElementRef(di), hostTNode.tViews as TView, getRenderer(), hostNode.data.queries);
|
||||
getOrCreateElementRef(di), hostTNode.tViews as TView, getRenderer(),
|
||||
hostNode.data[QUERIES]);
|
||||
}
|
||||
return di.templateRef;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
import {assertEqual} from './assert';
|
||||
import {DirectiveDef} from './interfaces/definition';
|
||||
import {TNodeFlags} from './interfaces/node';
|
||||
import {HookData, LView, LViewFlags, TView} from './interfaces/view';
|
||||
import {DIRECTIVES, FLAGS, HookData, LViewData, LViewFlags, TView} from './interfaces/view';
|
||||
|
||||
|
||||
/**
|
||||
|
@ -20,7 +20,7 @@ import {HookData, LView, LViewFlags, TView} from './interfaces/view';
|
|||
* directive index), then saved in the even indices of the initHooks array. The odd indices
|
||||
* hold the hook functions themselves.
|
||||
*
|
||||
* @param index The index of the directive in LView.data
|
||||
* @param index The index of the directive in LViewData[DIRECTIVES]
|
||||
* @param hooks The static hooks map on the directive def
|
||||
* @param tView The current TView
|
||||
*/
|
||||
|
@ -42,9 +42,8 @@ export function queueInitHooks(
|
|||
* Loops through the directives on a node and queues all their hooks except ngOnInit
|
||||
* and ngDoCheck, which are queued separately in directiveCreate.
|
||||
*/
|
||||
export function queueLifecycleHooks(flags: number, currentView: LView): void {
|
||||
const tView = currentView.tView;
|
||||
if (tView.firstTemplatePass === true) {
|
||||
export function queueLifecycleHooks(flags: number, tView: TView): void {
|
||||
if (tView.firstTemplatePass) {
|
||||
const start = flags >> TNodeFlags.DirectiveStartingIndexShift;
|
||||
const count = flags & TNodeFlags.DirectiveCountMask;
|
||||
const end = start + count;
|
||||
|
@ -97,10 +96,11 @@ function queueDestroyHooks(def: DirectiveDef<any>, tView: TView, i: number): voi
|
|||
*
|
||||
* @param currentView The current view
|
||||
*/
|
||||
export function executeInitHooks(currentView: LView, tView: TView, creationMode: boolean): void {
|
||||
if (currentView.flags & LViewFlags.RunInit) {
|
||||
executeHooks(currentView.directives !, tView.initHooks, tView.checkHooks, creationMode);
|
||||
currentView.flags &= ~LViewFlags.RunInit;
|
||||
export function executeInitHooks(
|
||||
currentView: LViewData, tView: TView, creationMode: boolean): void {
|
||||
if (currentView[FLAGS] & LViewFlags.RunInit) {
|
||||
executeHooks(currentView[DIRECTIVES] !, tView.initHooks, tView.checkHooks, creationMode);
|
||||
currentView[FLAGS] &= ~LViewFlags.RunInit;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -6,14 +6,30 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {LContainerNode, LElementNode, LViewNode} from './node';
|
||||
import {LElementNode, LViewNode} from './node';
|
||||
import {LQueries} from './query';
|
||||
import {LView, TView} from './view';
|
||||
import {LViewData, NEXT, PARENT, QUERIES} from './view';
|
||||
|
||||
/**
|
||||
* Below are constants for LContainer indices to help us look up LContainer members
|
||||
* without having to remember the specific indices.
|
||||
* Uglify will inline these when minifying so there shouldn't be a cost.
|
||||
*/
|
||||
export const ACTIVE_INDEX = 0;
|
||||
// PARENT, NEXT, and QUERIES are indices 1, 2, and 3.
|
||||
// As we already have these constants in LViewData, we don't need to re-create them.
|
||||
export const VIEWS = 4;
|
||||
export const RENDER_PARENT = 5;
|
||||
|
||||
|
||||
/** The state associated with an LContainer */
|
||||
export interface LContainer {
|
||||
/**
|
||||
* The state associated with an LContainerNode.
|
||||
*
|
||||
* This is an array so that its structure is closer to LViewData. This helps
|
||||
* when traversing the view tree (which is a mix of containers and component
|
||||
* views), so we can jump to viewOrContainer[NEXT] in the same way regardless
|
||||
* of type.
|
||||
*/
|
||||
export interface LContainer extends Array<any> {
|
||||
/**
|
||||
* The next active index in the views array to read or write to. This helps us
|
||||
* keep track of where we are in the views array.
|
||||
|
@ -21,19 +37,25 @@ export interface LContainer {
|
|||
* it is set to null to identify this scenario, as indices are "absolute" in that case,
|
||||
* i.e. provided directly by the user of the ViewContainerRef API.
|
||||
*/
|
||||
nextIndex: number|null;
|
||||
|
||||
/**
|
||||
* This allows us to jump from a container to a sibling container or
|
||||
* component view with the same parent, so we can remove listeners efficiently.
|
||||
*/
|
||||
next: LView|LContainer|null;
|
||||
[ACTIVE_INDEX]: number|null;
|
||||
|
||||
/**
|
||||
* Access to the parent view is necessary so we can propagate back
|
||||
* up from inside a container to parent.next.
|
||||
* up from inside a container to parent[NEXT].
|
||||
*/
|
||||
parent: LView|null;
|
||||
[PARENT]: LViewData|null;
|
||||
|
||||
/**
|
||||
* This allows us to jump from a container to a sibling container or component
|
||||
* view with the same parent, so we can remove listeners efficiently.
|
||||
*/
|
||||
[NEXT]: LViewData|LContainer|null;
|
||||
|
||||
/**
|
||||
* Queries active for this container - all the views inserted to / removed from
|
||||
* this container are reported to queries referenced here.
|
||||
*/
|
||||
[QUERIES]: LQueries|null;
|
||||
|
||||
/**
|
||||
* A list of the container's currently active child views. Views will be inserted
|
||||
|
@ -42,7 +64,7 @@ export interface LContainer {
|
|||
* (and don't need to be re-added) and so we can remove views from the DOM when they
|
||||
* are no longer required.
|
||||
*/
|
||||
readonly views: LViewNode[];
|
||||
[VIEWS]: LViewNode[];
|
||||
|
||||
/**
|
||||
* Parent Element which will contain the location where all of the Views will be
|
||||
|
@ -64,13 +86,7 @@ export interface LContainer {
|
|||
* - not `null`, then use the `projectedParent.native` as the `RElement` to insert
|
||||
* `LViewNode`s into.
|
||||
*/
|
||||
renderParent: LElementNode|null;
|
||||
|
||||
/**
|
||||
* Queries active for this container - all the views inserted to / removed from
|
||||
* this container are reported to queries referenced here.
|
||||
*/
|
||||
queries: LQueries|null;
|
||||
[RENDER_PARENT]: LElementNode|null;
|
||||
}
|
||||
|
||||
// Note: This hack is necessary so we don't erroneously get a circular dependency
|
||||
|
|
|
@ -10,8 +10,8 @@ import {LContainer} from './container';
|
|||
import {LInjector} from './injector';
|
||||
import {LProjection} from './projection';
|
||||
import {LQueries} from './query';
|
||||
import {RElement, RNode, RText} from './renderer';
|
||||
import {LView, TData, TView} from './view';
|
||||
import {RElement, RText} from './renderer';
|
||||
import {LViewData, TView} from './view';
|
||||
|
||||
|
||||
|
||||
|
@ -72,7 +72,7 @@ export interface LNode {
|
|||
* If LContainerNode, then `data` contains LContainer.
|
||||
* If LProjectionNode, then `data` contains LProjection.
|
||||
*/
|
||||
readonly data: LView|LContainer|LProjection|null;
|
||||
readonly data: LViewData|LContainer|LProjection|null;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -80,7 +80,7 @@ export interface LNode {
|
|||
*
|
||||
* When the injector is walking up a tree, it needs access to the `directives` (part of view).
|
||||
*/
|
||||
readonly view: LView;
|
||||
readonly view: LViewData;
|
||||
|
||||
/** The injector associated with this node. Necessary for DI. */
|
||||
nodeInjector: LInjector|null;
|
||||
|
@ -120,7 +120,7 @@ export interface LElementNode extends LNode {
|
|||
readonly native: RElement;
|
||||
|
||||
/** If Component then data has LView (light DOM) */
|
||||
readonly data: LView|null;
|
||||
readonly data: LViewData|null;
|
||||
}
|
||||
|
||||
/** LNode representing a #text node. */
|
||||
|
@ -134,7 +134,7 @@ export interface LTextNode extends LNode {
|
|||
/** Abstract node which contains root nodes of a view. */
|
||||
export interface LViewNode extends LNode {
|
||||
readonly native: null;
|
||||
readonly data: LView;
|
||||
readonly data: LViewData;
|
||||
dynamicLContainerNode: null;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ import {LNode} from './node';
|
|||
/** Used for tracking queries (e.g. ViewChild, ContentChild). */
|
||||
export interface LQueries {
|
||||
/**
|
||||
* Used to ask queries if those should be cloned to the child element.
|
||||
* Used to ask querieis if those should be cloned to the child element.
|
||||
*
|
||||
* For example in the case of deep queries the `child()` returns
|
||||
* queries for the child node. In case of shallow queries it returns
|
||||
|
|
|
@ -15,28 +15,68 @@ import {LElementNode, LViewNode, TNode} from './node';
|
|||
import {LQueries} from './query';
|
||||
import {Renderer3} from './renderer';
|
||||
|
||||
/** Size of LViewData's header. Necessary to adjust for it when setting slots. */
|
||||
export const HEADER_OFFSET = 14;
|
||||
|
||||
// Below are constants for LViewData indices to help us look up LViewData members
|
||||
// without having to remember the specific indices.
|
||||
// Uglify will inline these when minifying so there shouldn't be a cost.
|
||||
export const TVIEW = 0;
|
||||
export const PARENT = 1;
|
||||
export const NEXT = 2;
|
||||
export const QUERIES = 3;
|
||||
export const FLAGS = 4;
|
||||
export const HOST_NODE = 5;
|
||||
export const BINDING_INDEX = 6;
|
||||
export const DIRECTIVES = 7;
|
||||
export const CLEANUP = 8;
|
||||
export const CONTEXT = 9;
|
||||
export const INJECTOR = 10;
|
||||
export const RENDERER = 11;
|
||||
export const SANITIZER = 12;
|
||||
export const TAIL = 13;
|
||||
|
||||
/**
|
||||
* `LView` stores all of the information needed to process the instructions as
|
||||
* `LViewData` stores all of the information needed to process the instructions as
|
||||
* they are invoked from the template. Each embedded view and component view has its
|
||||
* own `LView`. When processing a particular view, we set the `currentView` to that
|
||||
* `LView`. When that view is done processing, the `currentView` is set back to
|
||||
* whatever the original `currentView` was before (the parent `LView`).
|
||||
* own `LViewData`. When processing a particular view, we set the `viewData` to that
|
||||
* `LViewData`. When that view is done processing, the `viewData` is set back to
|
||||
* whatever the original `viewData` was before (the parent `LViewData`).
|
||||
*
|
||||
* Keeping separate state for each view facilities view insertion / deletion, so we
|
||||
* don't have to edit the data array based on which views are present.
|
||||
*/
|
||||
export interface LView {
|
||||
/** Flags for this view (see LViewFlags for definition of each bit). */
|
||||
flags: LViewFlags;
|
||||
export interface LViewData extends Array<any> {
|
||||
/**
|
||||
* The static data for this view. We need a reference to this so we can easily walk up the
|
||||
* node tree in DI and get the TView.data array associated with a node (where the
|
||||
* directive defs are stored).
|
||||
*/
|
||||
[TVIEW]: TView;
|
||||
|
||||
/**
|
||||
* The parent view is needed when we exit the view and must restore the previous
|
||||
* `LView`. Without this, the render method would have to keep a stack of
|
||||
* `LViewData`. Without this, the render method would have to keep a stack of
|
||||
* views as it is recursively rendering templates.
|
||||
*/
|
||||
readonly parent: LView|null;
|
||||
[PARENT]: LViewData|null;
|
||||
|
||||
/**
|
||||
*
|
||||
* The next sibling LViewData or LContainer.
|
||||
*
|
||||
* Allows us to propagate between sibling view states that aren't in the same
|
||||
* container. Embedded views already have a node.next, but it is only set for
|
||||
* views in the same container. We need a way to link component views and views
|
||||
* across containers as well.
|
||||
*/
|
||||
[NEXT]: LViewData|LContainer|null;
|
||||
|
||||
/** Queries active for this view - nodes from a view are reported to those queries. */
|
||||
[QUERIES]: LQueries|null;
|
||||
|
||||
/** Flags for this view. See LViewFlags for more info. */
|
||||
[FLAGS]: LViewFlags;
|
||||
|
||||
/**
|
||||
* Pointer to the `LViewNode` or `LElementNode` which represents the root of the view.
|
||||
|
@ -46,11 +86,8 @@ export interface LView {
|
|||
*
|
||||
* If `LElementNode`, this is the LView of a component.
|
||||
*/
|
||||
// TODO(kara): Remove when we have parent/child on TNodes
|
||||
readonly node: LViewNode|LElementNode;
|
||||
|
||||
/** Renderer to be used for this view. */
|
||||
readonly renderer: Renderer3;
|
||||
// TODO(kara): Replace with index
|
||||
[HOST_NODE]: LViewNode|LElementNode;
|
||||
|
||||
/**
|
||||
* The binding index we should access next.
|
||||
|
@ -59,7 +96,16 @@ export interface LView {
|
|||
* if a view is left midway through processing bindings (e.g. if there is
|
||||
* a setter that creates an embedded view, like in ngIf).
|
||||
*/
|
||||
bindingIndex: number;
|
||||
[BINDING_INDEX]: number;
|
||||
|
||||
/**
|
||||
* An array of directive instances in the current view.
|
||||
*
|
||||
* These must be stored separately from LNodes because their presence is
|
||||
* unknown at compile-time and thus space cannot be reserved in data[].
|
||||
*/
|
||||
// TODO: flatten into LViewData[]
|
||||
[DIRECTIVES]: any[]|null;
|
||||
|
||||
/**
|
||||
* When a view is destroyed, listeners need to be released and outputs need to be
|
||||
|
@ -69,79 +115,36 @@ export interface LView {
|
|||
* These change per LView instance, so they cannot be stored on TView. Instead,
|
||||
* TView.cleanup saves an index to the necessary context in this array.
|
||||
*/
|
||||
// TODO: collapse into data[]
|
||||
cleanupInstances: any[]|null;
|
||||
|
||||
/**
|
||||
* The last LView or LContainer beneath this LView in the hierarchy.
|
||||
*
|
||||
* The tail allows us to quickly add a new state to the end of the view list
|
||||
* without having to propagate starting from the first child.
|
||||
*/
|
||||
tail: LView|LContainer|null;
|
||||
|
||||
/**
|
||||
* The next sibling LView or LContainer.
|
||||
*
|
||||
* Allows us to propagate between sibling view states that aren't in the same
|
||||
* container. Embedded views already have a node.next, but it is only set for
|
||||
* views in the same container. We need a way to link component views and views
|
||||
* across containers as well.
|
||||
*/
|
||||
next: LView|LContainer|null;
|
||||
|
||||
/**
|
||||
* This array stores all element/text/container nodes created inside this view
|
||||
* and their bindings. Stored as an array rather than a linked list so we can
|
||||
* look up nodes directly in the case of forward declaration or bindings
|
||||
* (e.g. E(1)).
|
||||
*
|
||||
* All bindings for a given view are stored in the order in which they
|
||||
* appear in the template, starting with `bindingStartIndex`.
|
||||
* We use `bindingIndex` to internally keep track of which binding
|
||||
* is currently active.
|
||||
*/
|
||||
readonly data: any[];
|
||||
|
||||
/**
|
||||
* An array of directive instances in the current view.
|
||||
*
|
||||
* These must be stored separately from LNodes because their presence is
|
||||
* unknown at compile-time and thus space cannot be reserved in data[].
|
||||
*/
|
||||
directives: any[]|null;
|
||||
|
||||
/**
|
||||
* The static data for this view. We need a reference to this so we can easily walk up the
|
||||
* node tree in DI and get the TView.data array associated with a node (where the
|
||||
* directive defs are stored).
|
||||
*/
|
||||
tView: TView;
|
||||
// TODO: flatten into LViewData[]
|
||||
[CLEANUP]: any[]|null;
|
||||
|
||||
/**
|
||||
* - For embedded views, the context with which to render the template.
|
||||
* - For root view of the root component the context contains change detection data.
|
||||
* - `null` otherwise.
|
||||
*/
|
||||
context: {}|RootContext|null;
|
||||
*/
|
||||
[CONTEXT]: {}|RootContext|null;
|
||||
|
||||
/** An optional Module Injector to be used as fall back after Element Injectors are consulted. */
|
||||
[INJECTOR]: Injector|null;
|
||||
|
||||
/** Renderer to be used for this view. */
|
||||
[RENDERER]: Renderer3;
|
||||
|
||||
/** An optional custom sanitizer. */
|
||||
[SANITIZER]: Sanitizer|null;
|
||||
|
||||
/**
|
||||
* Queries active for this view - nodes from a view are reported to those queries
|
||||
* The last LViewData or LContainer beneath this LViewData in the hierarchy.
|
||||
*
|
||||
* The tail allows us to quickly add a new state to the end of the view list
|
||||
* without having to propagate starting from the first child.
|
||||
*/
|
||||
queries: LQueries|null;
|
||||
|
||||
/**
|
||||
* An optional Module Injector to be used as fall back after Element Injectors are consulted.
|
||||
*/
|
||||
injector: Injector|null;
|
||||
|
||||
/**
|
||||
* An optional custom sanitizer
|
||||
*/
|
||||
sanitizer: Sanitizer|null;
|
||||
// TODO: replace with global
|
||||
[TAIL]: LViewData|LContainer|null;
|
||||
}
|
||||
|
||||
/** Flags associated with an LView (saved in LView.flags) */
|
||||
/** Flags associated with an LView (saved in LViewData[FLAGS]) */
|
||||
export const enum LViewFlags {
|
||||
/**
|
||||
* Whether or not the view is in creationMode.
|
||||
|
@ -175,14 +178,6 @@ export const enum LViewFlags {
|
|||
Destroyed = 0b100000,
|
||||
}
|
||||
|
||||
/** Interface necessary to work with view tree traversal */
|
||||
export interface LViewOrLContainer {
|
||||
next: LView|LContainer|null;
|
||||
views?: LViewNode[];
|
||||
tView?: TView;
|
||||
parent: LView|null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The static data for an LView (shared between all templates of a
|
||||
* given type).
|
||||
|
@ -388,7 +383,7 @@ export interface TView {
|
|||
* refreshed when the current view has finished its check.
|
||||
*
|
||||
* Even indices: Directive indices
|
||||
* Odd indices: Element indices
|
||||
* Odd indices: Element indices (adjusted for LViewData header offset)
|
||||
*/
|
||||
components: number[]|null;
|
||||
|
||||
|
@ -397,6 +392,9 @@ export interface TView {
|
|||
*
|
||||
* Even indices: Directive indices
|
||||
* Odd indices: Element indices
|
||||
*
|
||||
* Element indices are NOT adjusted for LViewData header offset because
|
||||
* they will be fed into instructions that expect the raw index (e.g. elementProperty)
|
||||
*/
|
||||
hostBindings: number[]|null;
|
||||
}
|
||||
|
|
|
@ -6,13 +6,12 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {assertDefined} from './assert';
|
||||
import {callHooks} from './hooks';
|
||||
import {LContainer, unusedValueExportToPlacateAjd as unused1} from './interfaces/container';
|
||||
import {LContainerNode, LElementNode, LNode, LProjectionNode, LTextNode, LViewNode, TNodeFlags, TNodeType, unusedValueExportToPlacateAjd as unused2} from './interfaces/node';
|
||||
import {LContainer, RENDER_PARENT, VIEWS, unusedValueExportToPlacateAjd as unused1} from './interfaces/container';
|
||||
import {LContainerNode, LElementNode, LNode, LProjectionNode, LTextNode, LViewNode, TNodeType, unusedValueExportToPlacateAjd as unused2} from './interfaces/node';
|
||||
import {unusedValueExportToPlacateAjd as unused3} from './interfaces/projection';
|
||||
import {ProceduralRenderer3, RElement, RNode, RText, Renderer3, isProceduralRenderer, unusedValueExportToPlacateAjd as unused4} from './interfaces/renderer';
|
||||
import {HookData, LView, LViewFlags, LViewOrLContainer, TView, unusedValueExportToPlacateAjd as unused5} from './interfaces/view';
|
||||
import {CLEANUP, DIRECTIVES, FLAGS, HEADER_OFFSET, HOST_NODE, HookData, LViewData, LViewFlags, NEXT, PARENT, QUERIES, RENDERER, TVIEW, unusedValueExportToPlacateAjd as unused5} from './interfaces/view';
|
||||
import {assertNodeType} from './node_assert';
|
||||
import {stringify} from './util';
|
||||
|
||||
|
@ -69,17 +68,17 @@ function findNextRNodeSibling(node: LNode | null, stopNode: LNode | null): RElem
|
|||
export function getNextLNode(node: LNode): LNode|null {
|
||||
// View nodes don't have TNodes, so their next must be retrieved through their LView.
|
||||
if (node.tNode.type === TNodeType.View) {
|
||||
const lView = node.data as LView;
|
||||
return lView.next ? (lView.next as LView).node : null;
|
||||
const viewData = node.data as LViewData;
|
||||
return viewData[NEXT] ? (viewData[NEXT] as LViewData)[HOST_NODE] : null;
|
||||
}
|
||||
return node.tNode.next ? node.view.data[node.tNode.next !.index] : null;
|
||||
return node.tNode.next ? node.view[node.tNode.next !.index] : null;
|
||||
}
|
||||
|
||||
/** Retrieves the first child of a given node */
|
||||
export function getChildLNode(node: LNode): LNode|null {
|
||||
if (node.tNode.child) {
|
||||
const view = node.tNode.type === TNodeType.View ? node.data as LView : node.view;
|
||||
return view.data[node.tNode.child.index];
|
||||
const viewData = node.tNode.type === TNodeType.View ? node.data as LViewData : node.view;
|
||||
return viewData[node.tNode.child.index];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -92,7 +91,7 @@ export function getParentLNode(node: LNode): LElementNode|LContainerNode|LViewNo
|
|||
export function getParentLNode(node: LNode): LElementNode|LContainerNode|LViewNode|null {
|
||||
if (node.tNode.index === -1) return null;
|
||||
const parent = node.tNode.parent;
|
||||
return parent ? node.view.data[parent.index] : node.view.node;
|
||||
return parent ? node.view[parent.index] : node.view[HOST_NODE];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -213,10 +212,10 @@ function walkLNodeTree(
|
|||
lContainerNode.dynamicLContainerNode.data :
|
||||
lContainerNode.data;
|
||||
if (renderParentNode) {
|
||||
childContainerData.renderParent = renderParentNode;
|
||||
childContainerData[RENDER_PARENT] = renderParentNode;
|
||||
}
|
||||
nextNode =
|
||||
childContainerData.views.length ? getChildLNode(childContainerData.views[0]) : null;
|
||||
childContainerData[VIEWS].length ? getChildLNode(childContainerData[VIEWS][0]) : null;
|
||||
} else if (node.tNode.type === TNodeType.Projection) {
|
||||
// For Projection look at the first projected node
|
||||
nextNode = (node as LProjectionNode).data.head;
|
||||
|
@ -256,11 +255,11 @@ export function addRemoveViewFromContainer(
|
|||
beforeNode?: RNode | null): void {
|
||||
ngDevMode && assertNodeType(container, TNodeType.Container);
|
||||
ngDevMode && assertNodeType(rootNode, TNodeType.View);
|
||||
const parentNode = container.data.renderParent;
|
||||
const parentNode = container.data[RENDER_PARENT];
|
||||
const parent = parentNode ? parentNode.native : null;
|
||||
if (parent) {
|
||||
let node: LNode|null = getChildLNode(rootNode);
|
||||
const renderer = container.view.renderer;
|
||||
const renderer = container.view[RENDERER];
|
||||
walkLNodeTree(
|
||||
node, rootNode, insertMode ? WalkLNodeTreeAction.Insert : WalkLNodeTreeAction.Detach,
|
||||
renderer, parentNode, beforeNode);
|
||||
|
@ -280,38 +279,35 @@ export function addRemoveViewFromContainer(
|
|||
*
|
||||
* @param rootView The view to destroy
|
||||
*/
|
||||
export function destroyViewTree(rootView: LView): void {
|
||||
export function destroyViewTree(rootView: LViewData): void {
|
||||
// If the view has no children, we can clean it up and return early.
|
||||
if (rootView.tView.childIndex === -1) {
|
||||
if (rootView[TVIEW].childIndex === -1) {
|
||||
return cleanUpView(rootView);
|
||||
}
|
||||
let viewOrContainer: LViewOrLContainer|null = getLViewChild(rootView);
|
||||
let viewOrContainer: LViewData|LContainer|null = getLViewChild(rootView);
|
||||
|
||||
while (viewOrContainer) {
|
||||
let next: LViewOrLContainer|null = null;
|
||||
let next: LViewData|LContainer|null = null;
|
||||
|
||||
if (viewOrContainer.views && viewOrContainer.views.length) {
|
||||
next = viewOrContainer.views[0].data;
|
||||
} else if (viewOrContainer.tView && viewOrContainer.tView.childIndex > -1) {
|
||||
next = getLViewChild(viewOrContainer as LView);
|
||||
} else if (viewOrContainer.next) {
|
||||
// Only move to the side and clean if operating below rootView -
|
||||
// otherwise we would start cleaning up sibling views of the rootView.
|
||||
cleanUpView(viewOrContainer);
|
||||
next = viewOrContainer.next;
|
||||
if (viewOrContainer.length >= HEADER_OFFSET) {
|
||||
// If LViewData, traverse down to child.
|
||||
const view = viewOrContainer as LViewData;
|
||||
if (view[TVIEW].childIndex > -1) next = getLViewChild(view);
|
||||
} else {
|
||||
// If container, traverse down to its first LViewData.
|
||||
const container = viewOrContainer as LContainer;
|
||||
if (container[VIEWS].length) next = container[VIEWS][0].data;
|
||||
}
|
||||
|
||||
if (next == null) {
|
||||
// If the viewOrContainer is the rootView and next is null it means that we are dealing
|
||||
// with a root view that doesn't have children. We didn't descend into child views
|
||||
// so no need to go back up the views tree.
|
||||
while (viewOrContainer && !viewOrContainer !.next && viewOrContainer !== rootView) {
|
||||
// Only clean up view when moving to the side or up, as destroy hooks
|
||||
// should be called in order from the bottom up.
|
||||
while (viewOrContainer && !viewOrContainer ![NEXT] && viewOrContainer !== rootView) {
|
||||
cleanUpView(viewOrContainer);
|
||||
viewOrContainer = getParentState(viewOrContainer, rootView);
|
||||
}
|
||||
cleanUpView(viewOrContainer || rootView);
|
||||
|
||||
next = viewOrContainer && viewOrContainer.next;
|
||||
next = viewOrContainer && viewOrContainer ![NEXT];
|
||||
}
|
||||
viewOrContainer = next;
|
||||
}
|
||||
|
@ -333,31 +329,31 @@ export function destroyViewTree(rootView: LView): void {
|
|||
export function insertView(
|
||||
container: LContainerNode, viewNode: LViewNode, index: number): LViewNode {
|
||||
const state = container.data;
|
||||
const views = state.views;
|
||||
const views = state[VIEWS];
|
||||
|
||||
if (index > 0) {
|
||||
// This is a new view, we need to add it to the children.
|
||||
views[index - 1].data.next = viewNode.data as LView;
|
||||
views[index - 1].data[NEXT] = viewNode.data as LViewData;
|
||||
}
|
||||
|
||||
if (index < views.length) {
|
||||
viewNode.data.next = views[index].data;
|
||||
viewNode.data[NEXT] = views[index].data;
|
||||
views.splice(index, 0, viewNode);
|
||||
} else {
|
||||
views.push(viewNode);
|
||||
viewNode.data.next = null;
|
||||
viewNode.data[NEXT] = null;
|
||||
}
|
||||
|
||||
// Notify query that a new view has been added
|
||||
const lView = viewNode.data;
|
||||
if (lView.queries) {
|
||||
lView.queries.insertView(index);
|
||||
if (lView[QUERIES]) {
|
||||
lView[QUERIES] !.insertView(index);
|
||||
}
|
||||
|
||||
// If the container's renderParent is null, we know that it is a root node of its own parent view
|
||||
// and we should wait until that parent processes its nodes (otherwise, we will insert this view's
|
||||
// nodes twice - once now and once when its parent inserts its views).
|
||||
if (container.data.renderParent !== null) {
|
||||
if (container.data[RENDER_PARENT] !== null) {
|
||||
let beforeNode = findNextRNodeSibling(viewNode, container);
|
||||
|
||||
if (!beforeNode) {
|
||||
|
@ -371,7 +367,7 @@ export function insertView(
|
|||
}
|
||||
|
||||
// Sets the attached flag
|
||||
viewNode.data.flags |= LViewFlags.Attached;
|
||||
viewNode.data[FLAGS] |= LViewFlags.Attached;
|
||||
|
||||
return viewNode;
|
||||
}
|
||||
|
@ -387,20 +383,20 @@ export function insertView(
|
|||
* @returns The detached view
|
||||
*/
|
||||
export function detachView(container: LContainerNode, removeIndex: number): LViewNode {
|
||||
const views = container.data.views;
|
||||
const views = container.data[VIEWS];
|
||||
const viewNode = views[removeIndex];
|
||||
if (removeIndex > 0) {
|
||||
views[removeIndex - 1].data.next = viewNode.data.next as LView;
|
||||
views[removeIndex - 1].data[NEXT] = viewNode.data[NEXT] as LViewData;
|
||||
}
|
||||
views.splice(removeIndex, 1);
|
||||
addRemoveViewFromContainer(container, viewNode, false);
|
||||
// Notify query that view has been removed
|
||||
const removedLview = viewNode.data;
|
||||
if (removedLview.queries) {
|
||||
removedLview.queries.removeView(removeIndex);
|
||||
if (removedLview[QUERIES]) {
|
||||
removedLview[QUERIES] !.removeView(removeIndex);
|
||||
}
|
||||
// Unsets the attached flag
|
||||
viewNode.data.flags &= ~LViewFlags.Attached;
|
||||
viewNode.data[FLAGS] &= ~LViewFlags.Attached;
|
||||
return viewNode;
|
||||
}
|
||||
|
||||
|
@ -412,17 +408,17 @@ export function detachView(container: LContainerNode, removeIndex: number): LVie
|
|||
* @returns The removed view
|
||||
*/
|
||||
export function removeView(container: LContainerNode, removeIndex: number): LViewNode {
|
||||
const viewNode = container.data.views[removeIndex];
|
||||
const viewNode = container.data[VIEWS][removeIndex];
|
||||
detachView(container, removeIndex);
|
||||
destroyLView(viewNode.data);
|
||||
return viewNode;
|
||||
}
|
||||
|
||||
/** Gets the child of the given LView */
|
||||
export function getLViewChild(view: LView): LView|LContainer|null {
|
||||
if (view.tView.childIndex === -1) return null;
|
||||
/** Gets the child of the given LViewData */
|
||||
export function getLViewChild(viewData: LViewData): LViewData|LContainer|null {
|
||||
if (viewData[TVIEW].childIndex === -1) return null;
|
||||
|
||||
const hostNode: LElementNode|LContainerNode = view.data[view.tView.childIndex];
|
||||
const hostNode: LElementNode|LContainerNode = viewData[viewData[TVIEW].childIndex];
|
||||
|
||||
return hostNode.data ? hostNode.data : (hostNode.dynamicLContainerNode as LContainerNode).data;
|
||||
}
|
||||
|
@ -433,14 +429,14 @@ export function getLViewChild(view: LView): LView|LContainer|null {
|
|||
*
|
||||
* @param view The view to be destroyed.
|
||||
*/
|
||||
export function destroyLView(view: LView) {
|
||||
const renderer = view.renderer;
|
||||
export function destroyLView(view: LViewData) {
|
||||
const renderer = view[RENDERER];
|
||||
if (isProceduralRenderer(renderer) && renderer.destroyNode) {
|
||||
walkLNodeTree(view.node, view.node, WalkLNodeTreeAction.Destroy, renderer);
|
||||
walkLNodeTree(view[HOST_NODE], view[HOST_NODE], WalkLNodeTreeAction.Destroy, renderer);
|
||||
}
|
||||
destroyViewTree(view);
|
||||
// Sets the destroyed flag
|
||||
view.flags |= LViewFlags.Destroyed;
|
||||
view[FLAGS] |= LViewFlags.Destroyed;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -455,76 +451,77 @@ export function destroyLView(view: LView) {
|
|||
* @param rootView The rootView, so we don't propagate too far up the view tree
|
||||
* @returns The correct parent LViewOrLContainer
|
||||
*/
|
||||
export function getParentState(state: LViewOrLContainer, rootView: LView): LViewOrLContainer|null {
|
||||
export function getParentState(state: LViewData | LContainer, rootView: LViewData): LViewData|
|
||||
LContainer|null {
|
||||
let node;
|
||||
if ((node = (state as LView) !.node) && node.tNode.type === TNodeType.View) {
|
||||
if ((node = (state as LViewData) ![HOST_NODE]) && node.tNode.type === TNodeType.View) {
|
||||
// if it's an embedded view, the state needs to go up to the container, in case the
|
||||
// container has a next
|
||||
return getParentLNode(node) !.data as any;
|
||||
} else {
|
||||
// otherwise, use parent view for containers or component views
|
||||
return state.parent === rootView ? null : state.parent;
|
||||
return state[PARENT] === rootView ? null : state[PARENT];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all listeners and call all onDestroys in a given view.
|
||||
*
|
||||
* @param view The LView to clean up
|
||||
* @param view The LViewData to clean up
|
||||
*/
|
||||
function cleanUpView(viewOrContainer: LViewOrLContainer): void {
|
||||
if ((viewOrContainer as LView).tView) {
|
||||
const view = viewOrContainer as LView;
|
||||
function cleanUpView(viewOrContainer: LViewData | LContainer): void {
|
||||
if ((viewOrContainer as LViewData)[TVIEW]) {
|
||||
const view = viewOrContainer as LViewData;
|
||||
removeListeners(view);
|
||||
executeOnDestroys(view);
|
||||
executePipeOnDestroys(view);
|
||||
// For component views only, the local renderer is destroyed as clean up time.
|
||||
if (view.tView.id === -1 && isProceduralRenderer(view.renderer)) {
|
||||
if (view[TVIEW].id === -1 && isProceduralRenderer(view[RENDERER])) {
|
||||
ngDevMode && ngDevMode.rendererDestroy++;
|
||||
view.renderer.destroy();
|
||||
(view[RENDERER] as ProceduralRenderer3).destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Removes listeners and unsubscribes from output subscriptions */
|
||||
function removeListeners(view: LView): void {
|
||||
const cleanup = view.tView.cleanup !;
|
||||
function removeListeners(viewData: LViewData): void {
|
||||
const cleanup = viewData[TVIEW].cleanup !;
|
||||
if (cleanup != null) {
|
||||
for (let i = 0; i < cleanup.length - 1; i += 2) {
|
||||
if (typeof cleanup[i] === 'string') {
|
||||
// This is a listener with the native renderer
|
||||
const native = view.data[cleanup[i + 1]].native;
|
||||
const listener = view.cleanupInstances ![cleanup[i + 2]];
|
||||
const native = viewData[cleanup[i + 1]].native;
|
||||
const listener = viewData[CLEANUP] ![cleanup[i + 2]];
|
||||
native.removeEventListener(cleanup[i], listener, cleanup[i + 3]);
|
||||
i += 2;
|
||||
} else if (typeof cleanup[i] === 'number') {
|
||||
// This is a listener with renderer2 (cleanup fn can be found by index)
|
||||
const cleanupFn = view.cleanupInstances ![cleanup[i]];
|
||||
const cleanupFn = viewData[CLEANUP] ![cleanup[i]];
|
||||
cleanupFn();
|
||||
} else {
|
||||
// This is a cleanup function that is grouped with the index of its context
|
||||
const context = view.cleanupInstances ![cleanup[i + 1]];
|
||||
const context = viewData[CLEANUP] ![cleanup[i + 1]];
|
||||
cleanup[i].call(context);
|
||||
}
|
||||
}
|
||||
view.cleanupInstances = null;
|
||||
viewData[CLEANUP] = null;
|
||||
}
|
||||
}
|
||||
|
||||
/** Calls onDestroy hooks for this view */
|
||||
function executeOnDestroys(view: LView): void {
|
||||
const tView = view.tView;
|
||||
function executeOnDestroys(view: LViewData): void {
|
||||
const tView = view[TVIEW];
|
||||
let destroyHooks: HookData|null;
|
||||
if (tView != null && (destroyHooks = tView.destroyHooks) != null) {
|
||||
callHooks(view.directives !, destroyHooks);
|
||||
callHooks(view[DIRECTIVES] !, destroyHooks);
|
||||
}
|
||||
}
|
||||
|
||||
/** Calls pipe destroy hooks for this view */
|
||||
function executePipeOnDestroys(view: LView): void {
|
||||
const pipeDestroyHooks = view.tView && view.tView.pipeDestroyHooks;
|
||||
function executePipeOnDestroys(viewData: LViewData): void {
|
||||
const pipeDestroyHooks = viewData[TVIEW] && viewData[TVIEW].pipeDestroyHooks;
|
||||
if (pipeDestroyHooks) {
|
||||
callHooks(view.data !, pipeDestroyHooks);
|
||||
callHooks(viewData !, pipeDestroyHooks);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -545,7 +542,7 @@ function executePipeOnDestroys(view: LView): void {
|
|||
* @param currentView The LView being processed
|
||||
* @return boolean Whether the child element should be inserted.
|
||||
*/
|
||||
export function canInsertNativeNode(parent: LNode, currentView: LView): boolean {
|
||||
export function canInsertNativeNode(parent: LNode, currentView: LViewData): boolean {
|
||||
const parentIsElement = parent.tNode.type === TNodeType.Element;
|
||||
|
||||
return parentIsElement &&
|
||||
|
@ -562,10 +559,10 @@ export function canInsertNativeNode(parent: LNode, currentView: LView): boolean
|
|||
* @param currentView The current LView
|
||||
* @returns Whether or not the child was appended
|
||||
*/
|
||||
export function appendChild(parent: LNode, child: RNode | null, currentView: LView): boolean {
|
||||
export function appendChild(parent: LNode, child: RNode | null, currentView: LViewData): boolean {
|
||||
if (child !== null && canInsertNativeNode(parent, currentView)) {
|
||||
// We only add element if not in View or not projected.
|
||||
const renderer = currentView.renderer;
|
||||
const renderer = currentView[RENDERER];
|
||||
isProceduralRenderer(renderer) ? renderer.appendChild(parent.native !as RElement, child) :
|
||||
parent.native !.appendChild(child);
|
||||
return true;
|
||||
|
@ -583,7 +580,7 @@ export function appendChild(parent: LNode, child: RNode | null, currentView: LVi
|
|||
*/
|
||||
export function appendProjectedNode(
|
||||
node: LElementNode | LTextNode | LContainerNode, currentParent: LElementNode,
|
||||
currentView: LView): void {
|
||||
currentView: LViewData): void {
|
||||
if (node.tNode.type !== TNodeType.Container) {
|
||||
appendChild(currentParent, (node as LElementNode | LTextNode).native, currentView);
|
||||
} else {
|
||||
|
@ -593,13 +590,13 @@ export function appendProjectedNode(
|
|||
// and can't be re-projected (as not content of any component).
|
||||
// Assignee the final projection location in those cases.
|
||||
const lContainer = (node as LContainerNode).data;
|
||||
lContainer.renderParent = currentParent;
|
||||
const views = lContainer.views;
|
||||
lContainer[RENDER_PARENT] = currentParent;
|
||||
const views = lContainer[VIEWS];
|
||||
for (let i = 0; i < views.length; i++) {
|
||||
addRemoveViewFromContainer(node as LContainerNode, views[i], true, null);
|
||||
}
|
||||
}
|
||||
if (node.dynamicLContainerNode) {
|
||||
node.dynamicLContainerNode.data.renderParent = currentParent;
|
||||
node.dynamicLContainerNode.data[RENDER_PARENT] = currentParent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import {PipeTransform} from '../change_detection/pipe_transform';
|
|||
|
||||
import {getTView, load, store} from './instructions';
|
||||
import {PipeDef, PipeDefList} from './interfaces/definition';
|
||||
import {HEADER_OFFSET} from './interfaces/view';
|
||||
import {pureFunction1, pureFunction2, pureFunction3, pureFunction4, pureFunctionV} from './pure_function';
|
||||
|
||||
/**
|
||||
|
@ -22,15 +23,17 @@ import {pureFunction1, pureFunction2, pureFunction3, pureFunction4, pureFunction
|
|||
export function pipe(index: number, pipeName: string): any {
|
||||
const tView = getTView();
|
||||
let pipeDef: PipeDef<any>;
|
||||
const adjustedIndex = index + HEADER_OFFSET;
|
||||
|
||||
if (tView.firstTemplatePass) {
|
||||
pipeDef = getPipeDef(pipeName, tView.pipeRegistry);
|
||||
tView.data[index] = pipeDef;
|
||||
tView.data[adjustedIndex] = pipeDef;
|
||||
if (pipeDef.onDestroy) {
|
||||
(tView.pipeDestroyHooks || (tView.pipeDestroyHooks = [])).push(index, pipeDef.onDestroy);
|
||||
(tView.pipeDestroyHooks || (tView.pipeDestroyHooks = [
|
||||
])).push(adjustedIndex, pipeDef.onDestroy);
|
||||
}
|
||||
} else {
|
||||
pipeDef = tView.data[index] as PipeDef<any>;
|
||||
pipeDef = tView.data[adjustedIndex] as PipeDef<any>;
|
||||
}
|
||||
|
||||
const pipeInstance = pipeDef.factory();
|
||||
|
@ -148,5 +151,5 @@ export function pipeBindV(index: number, slotOffset: number, values: any[]): any
|
|||
}
|
||||
|
||||
function isPure(index: number): boolean {
|
||||
return (<PipeDef<any>>getTView().data[index]).pure;
|
||||
return (<PipeDef<any>>getTView().data[index + HEADER_OFFSET]).pure;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import {DirectiveDef, unusedValueExportToPlacateAjd as unused1} from './interfac
|
|||
import {LInjector, unusedValueExportToPlacateAjd as unused2} from './interfaces/injector';
|
||||
import {LContainerNode, LElementNode, LNode, TNode, TNodeFlags, unusedValueExportToPlacateAjd as unused3} from './interfaces/node';
|
||||
import {LQueries, QueryReadType, unusedValueExportToPlacateAjd as unused4} from './interfaces/query';
|
||||
import {DIRECTIVES, TVIEW} from './interfaces/view';
|
||||
import {flatten} from './util';
|
||||
|
||||
const unusedValueToPlacateAjd = unused1 + unused2 + unused3 + unused4;
|
||||
|
@ -222,7 +223,7 @@ function getIdxOfMatchingSelector(tNode: TNode, selector: string): number|null {
|
|||
* @returns Index of a found directive or null when none found.
|
||||
*/
|
||||
function getIdxOfMatchingDirective(node: LNode, type: Type<any>): number|null {
|
||||
const defs = node.view.tView.directives !;
|
||||
const defs = node.view[TVIEW].directives !;
|
||||
const flags = node.tNode.flags;
|
||||
const count = flags & TNodeFlags.DirectiveCountMask;
|
||||
const start = flags >> TNodeFlags.DirectiveStartingIndexShift;
|
||||
|
@ -244,7 +245,7 @@ function readFromNodeInjector(
|
|||
} else {
|
||||
const matchingIdx = getIdxOfMatchingDirective(node, read as Type<any>);
|
||||
if (matchingIdx !== null) {
|
||||
return node.view.directives ![matchingIdx];
|
||||
return node.view[DIRECTIVES] ![matchingIdx];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -416,7 +417,7 @@ export function query<T>(
|
|||
const queryList = new QueryList<T>();
|
||||
const queries = getCurrentQueries(LQueries_);
|
||||
queries.track(queryList, predicate, descend, read);
|
||||
storeCleanupWithContext(undefined, queryList, queryList.destroy);
|
||||
storeCleanupWithContext(null, queryList, queryList.destroy);
|
||||
if (memoryIndex != null) {
|
||||
store(memoryIndex, queryList);
|
||||
}
|
||||
|
|
|
@ -11,10 +11,10 @@ import {ChangeDetectorRef as viewEngine_ChangeDetectorRef} from '../change_detec
|
|||
import {ViewContainerRef as viewEngine_ViewContainerRef} from '../linker/view_container_ref';
|
||||
import {EmbeddedViewRef as viewEngine_EmbeddedViewRef, InternalViewRef as viewEngine_InternalViewRef} from '../linker/view_ref';
|
||||
|
||||
import {checkNoChanges, detectChanges, markViewDirty, storeCleanupFn} from './instructions';
|
||||
import {checkNoChanges, detectChanges, markViewDirty, storeCleanupFn, viewAttached} from './instructions';
|
||||
import {ComponentTemplate} from './interfaces/definition';
|
||||
import {LViewNode} from './interfaces/node';
|
||||
import {LView, LViewFlags} from './interfaces/view';
|
||||
import {FLAGS, LViewData, LViewFlags} from './interfaces/view';
|
||||
import {destroyLView} from './node_manipulation';
|
||||
|
||||
// Needed due to tsickle downleveling where multiple `implements` with classes creates
|
||||
|
@ -29,16 +29,16 @@ export class ViewRef<T> implements viewEngine_EmbeddedViewRef<T>, viewEngine_Int
|
|||
context: T;
|
||||
rootNodes: any[];
|
||||
|
||||
constructor(protected _view: LView, context: T|null) { this.context = context !; }
|
||||
constructor(protected _view: LViewData, context: T|null) { this.context = context !; }
|
||||
|
||||
/** @internal */
|
||||
_setComponentContext(view: LView, context: T) {
|
||||
_setComponentContext(view: LViewData, context: T) {
|
||||
this._view = view;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
get destroyed(): boolean {
|
||||
return (this._view.flags & LViewFlags.Destroyed) === LViewFlags.Destroyed;
|
||||
return (this._view[FLAGS] & LViewFlags.Destroyed) === LViewFlags.Destroyed;
|
||||
}
|
||||
|
||||
destroy(): void { destroyLView(this._view); }
|
||||
|
@ -132,7 +132,7 @@ export class ViewRef<T> implements viewEngine_EmbeddedViewRef<T>, viewEngine_Int
|
|||
* }
|
||||
* ```
|
||||
*/
|
||||
detach(): void { this._view.flags &= ~LViewFlags.Attached; }
|
||||
detach(): void { this._view[FLAGS] &= ~LViewFlags.Attached; }
|
||||
|
||||
/**
|
||||
* Re-attaches a view to the change detection tree.
|
||||
|
@ -189,7 +189,7 @@ export class ViewRef<T> implements viewEngine_EmbeddedViewRef<T>, viewEngine_Int
|
|||
* }
|
||||
* ```
|
||||
*/
|
||||
reattach(): void { this._view.flags |= LViewFlags.Attached; }
|
||||
reattach(): void { this._view[FLAGS] |= LViewFlags.Attached; }
|
||||
|
||||
/**
|
||||
* Checks the view and its children.
|
||||
|
@ -240,8 +240,7 @@ export class EmbeddedViewRef<T> extends ViewRef<T> {
|
|||
}
|
||||
|
||||
destroy(): void {
|
||||
if (this._viewContainerRef &&
|
||||
(this._view.flags & LViewFlags.Attached) === LViewFlags.Attached) {
|
||||
if (this._viewContainerRef && viewAttached(this._view)) {
|
||||
this._viewContainerRef.detach(this._viewContainerRef.indexOf(this));
|
||||
this._viewContainerRef = null;
|
||||
}
|
||||
|
|
|
@ -1,31 +1,82 @@
|
|||
[
|
||||
{
|
||||
"name": "ACTIVE_INDEX"
|
||||
},
|
||||
{
|
||||
"name": "BINDING_INDEX"
|
||||
},
|
||||
{
|
||||
"name": "CLEAN_PROMISE"
|
||||
},
|
||||
{
|
||||
"name": "CONTEXT"
|
||||
},
|
||||
{
|
||||
"name": "DIRECTIVES"
|
||||
},
|
||||
{
|
||||
"name": "EMPTY$2"
|
||||
},
|
||||
{
|
||||
"name": "EMPTY_RENDERER_TYPE_ID"
|
||||
},
|
||||
{
|
||||
"name": "FLAGS"
|
||||
},
|
||||
{
|
||||
"name": "HEADER_FILLER"
|
||||
},
|
||||
{
|
||||
"name": "HEADER_OFFSET"
|
||||
},
|
||||
{
|
||||
"name": "HOST_NODE"
|
||||
},
|
||||
{
|
||||
"name": "HelloWorld"
|
||||
},
|
||||
{
|
||||
"name": "INJECTOR$1"
|
||||
},
|
||||
{
|
||||
"name": "INeedToExistEvenThoughIAmNotNeeded"
|
||||
},
|
||||
{
|
||||
"name": "NEXT"
|
||||
},
|
||||
{
|
||||
"name": "NG_HOST_SYMBOL"
|
||||
},
|
||||
{
|
||||
"name": "NG_PROJECT_AS_ATTR_NAME"
|
||||
},
|
||||
{
|
||||
"name": "QUERIES"
|
||||
},
|
||||
{
|
||||
"name": "RENDERER"
|
||||
},
|
||||
{
|
||||
"name": "ROOT_DIRECTIVE_INDICES"
|
||||
},
|
||||
{
|
||||
"name": "SANITIZER"
|
||||
},
|
||||
{
|
||||
"name": "TVIEW"
|
||||
},
|
||||
{
|
||||
"name": "UNDEFINED_RENDERER_TYPE_ID"
|
||||
},
|
||||
{
|
||||
"name": "VIEWS"
|
||||
},
|
||||
{
|
||||
"name": "_CLEAN_PROMISE"
|
||||
},
|
||||
{
|
||||
"name": "_ROOT_DIRECTIVE_INDICES"
|
||||
},
|
||||
{
|
||||
"name": "_renderCompCount"
|
||||
},
|
||||
|
@ -54,7 +105,7 @@
|
|||
"name": "createLNodeObject"
|
||||
},
|
||||
{
|
||||
"name": "createLView"
|
||||
"name": "createLViewData"
|
||||
},
|
||||
{
|
||||
"name": "createRootContext"
|
||||
|
@ -68,9 +119,6 @@
|
|||
{
|
||||
"name": "createTextNode"
|
||||
},
|
||||
{
|
||||
"name": "currentView"
|
||||
},
|
||||
{
|
||||
"name": "defineComponent"
|
||||
},
|
||||
|
@ -131,9 +179,6 @@
|
|||
{
|
||||
"name": "invertObject"
|
||||
},
|
||||
{
|
||||
"name": "isLContainer"
|
||||
},
|
||||
{
|
||||
"name": "isProceduralRenderer"
|
||||
},
|
||||
|
|
|
@ -1,16 +1,31 @@
|
|||
[
|
||||
{
|
||||
"name": "ACTIVE_INDEX"
|
||||
},
|
||||
{
|
||||
"name": "BINDING_INDEX"
|
||||
},
|
||||
{
|
||||
"name": "BLOOM_SIZE"
|
||||
},
|
||||
{
|
||||
"name": "CIRCULAR$2"
|
||||
},
|
||||
{
|
||||
"name": "CLEANUP"
|
||||
},
|
||||
{
|
||||
"name": "CLEAN_PROMISE"
|
||||
},
|
||||
{
|
||||
"name": "CONTEXT"
|
||||
},
|
||||
{
|
||||
"name": "CommonModule"
|
||||
},
|
||||
{
|
||||
"name": "DIRECTIVES"
|
||||
},
|
||||
{
|
||||
"name": "DefaultIterableDiffer"
|
||||
},
|
||||
|
@ -29,12 +44,30 @@
|
|||
{
|
||||
"name": "EmbeddedViewRef$1"
|
||||
},
|
||||
{
|
||||
"name": "FLAGS"
|
||||
},
|
||||
{
|
||||
"name": "HEADER_FILLER"
|
||||
},
|
||||
{
|
||||
"name": "HEADER_OFFSET"
|
||||
},
|
||||
{
|
||||
"name": "HOST_NODE"
|
||||
},
|
||||
{
|
||||
"name": "INJECTOR$1"
|
||||
},
|
||||
{
|
||||
"name": "IterableChangeRecord_"
|
||||
},
|
||||
{
|
||||
"name": "IterableDiffers"
|
||||
},
|
||||
{
|
||||
"name": "NEXT"
|
||||
},
|
||||
{
|
||||
"name": "NG_ELEMENT_ID"
|
||||
},
|
||||
|
@ -65,15 +98,36 @@
|
|||
{
|
||||
"name": "PARAMETERS"
|
||||
},
|
||||
{
|
||||
"name": "PARENT"
|
||||
},
|
||||
{
|
||||
"name": "QUERIES"
|
||||
},
|
||||
{
|
||||
"name": "RENDERER"
|
||||
},
|
||||
{
|
||||
"name": "RENDER_PARENT"
|
||||
},
|
||||
{
|
||||
"name": "ROOT_DIRECTIVE_INDICES"
|
||||
},
|
||||
{
|
||||
"name": "RecordViewTuple"
|
||||
},
|
||||
{
|
||||
"name": "SANITIZER"
|
||||
},
|
||||
{
|
||||
"name": "SkipSelf"
|
||||
},
|
||||
{
|
||||
"name": "TAIL"
|
||||
},
|
||||
{
|
||||
"name": "TVIEW"
|
||||
},
|
||||
{
|
||||
"name": "TemplateRef$1"
|
||||
},
|
||||
|
@ -92,6 +146,9 @@
|
|||
{
|
||||
"name": "UNDEFINED_RENDERER_TYPE_ID"
|
||||
},
|
||||
{
|
||||
"name": "VIEWS"
|
||||
},
|
||||
{
|
||||
"name": "ViewContainerRef$1"
|
||||
},
|
||||
|
@ -264,7 +321,7 @@
|
|||
"name": "createLNodeObject"
|
||||
},
|
||||
{
|
||||
"name": "createLView"
|
||||
"name": "createLViewData"
|
||||
},
|
||||
{
|
||||
"name": "createOutput"
|
||||
|
@ -281,9 +338,6 @@
|
|||
{
|
||||
"name": "createTextNode"
|
||||
},
|
||||
{
|
||||
"name": "currentView"
|
||||
},
|
||||
{
|
||||
"name": "defineComponent"
|
||||
},
|
||||
|
@ -500,9 +554,6 @@
|
|||
{
|
||||
"name": "isJsObject"
|
||||
},
|
||||
{
|
||||
"name": "isLContainer"
|
||||
},
|
||||
{
|
||||
"name": "isListLikeIterable"
|
||||
},
|
||||
|
@ -530,6 +581,9 @@
|
|||
{
|
||||
"name": "load"
|
||||
},
|
||||
{
|
||||
"name": "loadInternal"
|
||||
},
|
||||
{
|
||||
"name": "locateHostElement"
|
||||
},
|
||||
|
|
|
@ -12,7 +12,7 @@ import {RenderFlags} from '@angular/core/src/render3/interfaces/definition';
|
|||
import {defineComponent} from '../../src/render3/definition';
|
||||
import {bloomAdd, bloomFindPossibleInjector, getOrCreateNodeInjector, injectAttribute} from '../../src/render3/di';
|
||||
import {NgOnChangesFeature, PublicFeature, defineDirective, directiveInject, injectChangeDetectorRef, injectElementRef, injectTemplateRef, injectViewContainerRef} from '../../src/render3/index';
|
||||
import {bind, container, containerRefreshEnd, containerRefreshStart, createLNode, createLView, createTView, elementEnd, elementStart, embeddedViewEnd, embeddedViewStart, enterView, interpolation2, leaveView, load, projection, projectionDef, text, textBinding} from '../../src/render3/instructions';
|
||||
import {bind, container, containerRefreshEnd, containerRefreshStart, createLNode, createLViewData, createTView, elementEnd, elementStart, embeddedViewEnd, embeddedViewStart, enterView, interpolation2, leaveView, load, projection, projectionDef, text, textBinding} from '../../src/render3/instructions';
|
||||
import {LInjector} from '../../src/render3/interfaces/injector';
|
||||
import {AttributeMarker, TNodeType} from '../../src/render3/interfaces/node';
|
||||
import {LViewFlags} from '../../src/render3/interfaces/view';
|
||||
|
@ -1404,7 +1404,7 @@ describe('di', () => {
|
|||
describe('getOrCreateNodeInjector', () => {
|
||||
it('should handle initial undefined state', () => {
|
||||
const contentView =
|
||||
createLView(null !, createTView(-1, null, null, null), null, LViewFlags.CheckAlways);
|
||||
createLViewData(null !, createTView(-1, null, null, null), null, LViewFlags.CheckAlways);
|
||||
const oldView = enterView(contentView, null !);
|
||||
try {
|
||||
const parent = createLNode(0, TNodeType.Element, null, null, null, null);
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
import {RenderFlags} from '@angular/core/src/render3';
|
||||
|
||||
import {defineComponent, defineDirective} from '../../src/render3/index';
|
||||
import {NO_CHANGE, bind, container, containerRefreshEnd, containerRefreshStart, elementAttribute, elementClassNamed, elementEnd, elementProperty, elementStart, elementStyleNamed, embeddedViewEnd, embeddedViewStart, interpolation1, interpolation2, interpolation3, interpolation4, interpolation5, interpolation6, interpolation7, interpolation8, interpolationV, load, loadDirective, projection, projectionDef, text, textBinding} from '../../src/render3/instructions';
|
||||
import {LViewFlags} from '../../src/render3/interfaces/view';
|
||||
import {NO_CHANGE, bind, container, containerRefreshEnd, containerRefreshStart, elementAttribute, elementClassNamed, elementEnd, elementProperty, elementStart, elementStyleNamed, embeddedViewEnd, embeddedViewStart, interpolation1, interpolation2, interpolation3, interpolation4, interpolation5, interpolation6, interpolation7, interpolation8, interpolationV, load, loadDirective, projection, projectionDef, text, textBinding,} from '../../src/render3/instructions';
|
||||
import {HEADER_OFFSET} from '../../src/render3/interfaces/view';
|
||||
import {sanitizeUrl} from '../../src/sanitization/sanitization';
|
||||
import {Sanitizer, SecurityContext} from '../../src/sanitization/security';
|
||||
|
||||
|
@ -849,8 +849,8 @@ describe('render3 integration test', () => {
|
|||
renderToHtml(Template, {condition: true});
|
||||
|
||||
const oldTemplateData = (Template as any).ngPrivateData;
|
||||
const oldContainerData = (oldTemplateData as any).data[0];
|
||||
const oldElementData = oldContainerData.tViews[0][0];
|
||||
const oldContainerData = (oldTemplateData as any).data[HEADER_OFFSET];
|
||||
const oldElementData = oldContainerData.tViews[0][HEADER_OFFSET];
|
||||
expect(oldContainerData).not.toBeNull();
|
||||
expect(oldElementData).not.toBeNull();
|
||||
|
||||
|
@ -858,8 +858,8 @@ describe('render3 integration test', () => {
|
|||
renderToHtml(Template, {condition: true});
|
||||
|
||||
const newTemplateData = (Template as any).ngPrivateData;
|
||||
const newContainerData = (oldTemplateData as any).data[0];
|
||||
const newElementData = oldContainerData.tViews[0][0];
|
||||
const newContainerData = (oldTemplateData as any).data[HEADER_OFFSET];
|
||||
const newElementData = oldContainerData.tViews[0][HEADER_OFFSET];
|
||||
expect(newTemplateData === oldTemplateData).toBe(true);
|
||||
expect(newContainerData === oldContainerData).toBe(true);
|
||||
expect(newElementData === oldElementData).toBe(true);
|
||||
|
|
Loading…
Reference in New Issue