refactor(ivy): remove LNode.view (#25988)

PR Close #25988
This commit is contained in:
Kara Erickson
2018-09-17 14:32:45 -07:00
committed by Ben Lesh
parent 5653874683
commit f47f2628e1
14 changed files with 172 additions and 159 deletions

View File

@ -14,13 +14,14 @@ import {Sanitizer} from '../sanitization/security';
import {assertComponentType, assertDefined} from './assert'; import {assertComponentType, assertDefined} from './assert';
import {queueInitHooks, queueLifecycleHooks} from './hooks'; import {queueInitHooks, queueLifecycleHooks} from './hooks';
import {CLEAN_PROMISE, _getComponentHostLElementNode, baseDirectiveCreate, createLViewData, createTView, detectChangesInternal, enterView, executeInitAndContentHooks, getRootView, hostElement, initChangeDetectorIfExisting, leaveView, locateHostElement, setHostBindings, queueHostBindingForCheck,} from './instructions'; import {CLEAN_PROMISE, baseDirectiveCreate, createLViewData, createTView, detectChangesInternal, enterView, executeInitAndContentHooks, getRootView, hostElement, initChangeDetectorIfExisting, leaveView, locateHostElement, setHostBindings, queueHostBindingForCheck,} from './instructions';
import {ComponentDef, ComponentDefInternal, ComponentType} from './interfaces/definition'; import {ComponentDef, ComponentDefInternal, ComponentType} from './interfaces/definition';
import {LElementNode} from './interfaces/node'; import {LElementNode} from './interfaces/node';
import {RElement, RendererFactory3, domRendererFactory3} from './interfaces/renderer'; import {RElement, RendererFactory3, domRendererFactory3} from './interfaces/renderer';
import {LViewData, LViewFlags, RootContext, INJECTOR, CONTEXT, TVIEW} from './interfaces/view'; import {LViewData, LViewFlags, RootContext, INJECTOR, CONTEXT, TVIEW} from './interfaces/view';
import {stringify} from './util'; import {stringify} from './util';
import {getComponentDef} from './definition'; import {getComponentDef} from './definition';
import {getLElementFromComponent, readPatchedLViewData} from './context_discovery';
/** Options that control how the component should be bootstrapped. */ /** Options that control how the component should be bootstrapped. */
@ -179,13 +180,12 @@ export function createRootContext(scheduler: (workFn: () => void) => void): Root
* ``` * ```
*/ */
export function LifecycleHooksFeature(component: any, def: ComponentDefInternal<any>): void { export function LifecycleHooksFeature(component: any, def: ComponentDefInternal<any>): void {
const elementNode = _getComponentHostLElementNode(component); const rootTView = readPatchedLViewData(component) ![TVIEW];
// Root component is always created at dir index 0 // Root component is always created at dir index 0
const tView = elementNode.view[TVIEW]; queueInitHooks(0, def.onInit, def.doCheck, rootTView);
queueInitHooks(0, def.onInit, def.doCheck, tView);
// Directive starting index 0, directive count 1 -> directive flags: 1 // Directive starting index 0, directive count 1 -> directive flags: 1
queueLifecycleHooks(1, tView); queueLifecycleHooks(1, rootTView);
} }
/** /**
@ -209,7 +209,7 @@ function getRootContext(component: any): RootContext {
* @param component Component for which the host element should be retrieved. * @param component Component for which the host element should be retrieved.
*/ */
export function getHostElement<T>(component: T): HTMLElement { export function getHostElement<T>(component: T): HTMLElement {
return _getComponentHostLElementNode(component).native as any; return getLElementFromComponent(component).native as any;
} }
/** /**

View File

@ -199,7 +199,7 @@ export function getLElementFromRootComponent(rootComponentInstance: {}): LElemen
* that `getContext` has in the event that an Angular application doesn't need to have * that `getContext` has in the event that an Angular application doesn't need to have
* any programmatic access to an element's context (only change detection uses this function). * any programmatic access to an element's context (only change detection uses this function).
*/ */
export function getLElementFromComponent(componentInstance: {}): LElementNode|null { export function getLElementFromComponent(componentInstance: {}): LElementNode {
let lViewData = readPatchedData(componentInstance); let lViewData = readPatchedData(componentInstance);
let lNode: LElementNode; let lNode: LElementNode;
@ -355,10 +355,9 @@ function getLNodeFromViewData(lViewData: LViewData, lElementIndex: number): LEle
*/ */
function discoverDirectiveIndices(lViewData: LViewData, lNodeIndex: number): number[]|null { function discoverDirectiveIndices(lViewData: LViewData, lNodeIndex: number): number[]|null {
const directivesAcrossView = lViewData[DIRECTIVES]; const directivesAcrossView = lViewData[DIRECTIVES];
const lNode = getLNodeFromViewData(lViewData, lNodeIndex);
const tNode = lViewData[TVIEW].data[lNodeIndex] as TNode; const tNode = lViewData[TVIEW].data[lNodeIndex] as TNode;
if (lNode && directivesAcrossView && directivesAcrossView.length) { if (directivesAcrossView && directivesAcrossView.length) {
// this check for tNode is to determine if the calue is a LEmementNode instance // this check for tNode is to determine if the value is a LElementNode instance
const directiveIndexStart = getDirectiveStartIndex(tNode); const directiveIndexStart = getDirectiveStartIndex(tNode);
const directiveIndexEnd = getDirectiveEndIndex(tNode, directiveIndexStart); const directiveIndexEnd = getDirectiveEndIndex(tNode, directiveIndexStart);
const directiveIndices: number[] = []; const directiveIndices: number[] = [];

View File

@ -26,17 +26,17 @@ import {Type} from '../type';
import {assertDefined, assertGreaterThan, assertLessThan} from './assert'; import {assertDefined, assertGreaterThan, assertLessThan} from './assert';
import {ComponentFactoryResolver} from './component_ref'; import {ComponentFactoryResolver} from './component_ref';
import {getComponentDef, getDirectiveDef, getPipeDef} from './definition'; import {getComponentDef, getDirectiveDef, getPipeDef} from './definition';
import {_getViewData, addToViewTree, assertPreviousIsParent, createEmbeddedViewAndNode, createLContainer, createLNodeObject, createTNode, getPreviousOrParentNode, getPreviousOrParentTNode, getRenderer, renderEmbeddedTemplate, resolveDirective} from './instructions'; import {_getViewData, addToViewTree, assertPreviousIsParent, createEmbeddedViewAndNode, createLContainer, createLNodeObject, createTNode, getPreviousOrParentNode, getPreviousOrParentTNode, getRenderer, loadElement, renderEmbeddedTemplate, resolveDirective} from './instructions';
import {RENDER_PARENT, VIEWS} from './interfaces/container'; import {LContainer, RENDER_PARENT, VIEWS} from './interfaces/container';
import {DirectiveDefInternal, RenderFlags} from './interfaces/definition'; import {DirectiveDefInternal, RenderFlags} from './interfaces/definition';
import {LInjector} from './interfaces/injector'; import {LInjector} from './interfaces/injector';
import {AttributeMarker, LContainerNode, LElementContainerNode, LElementNode, LNode, LNodeWithLocalRefs, TContainerNode, TElementNode, TNode, TNodeFlags, TNodeType, TViewNode} from './interfaces/node'; import {AttributeMarker, LContainerNode, LElementContainerNode, LElementNode, LNode, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeType, TViewNode} from './interfaces/node';
import {LQueries, QueryReadType} from './interfaces/query'; import {LQueries, QueryReadType} from './interfaces/query';
import {RElement, Renderer3, isProceduralRenderer} from './interfaces/renderer'; import {Renderer3, isProceduralRenderer} from './interfaces/renderer';
import {CONTEXT, DIRECTIVES, HOST_NODE, INJECTOR, LViewData, PARENT, QUERIES, RENDERER, TVIEW, TView} from './interfaces/view'; import {CONTEXT, DIRECTIVES, HOST_NODE, INJECTOR, LViewData, QUERIES, RENDERER, TVIEW, TView} from './interfaces/view';
import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert'; import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert';
import {addRemoveViewFromContainer, appendChild, detachView, findComponentView, getBeforeNodeForView, getHostElementNode, getParentLNode, getParentOrContainerNode, getRenderParent, insertView, removeView} from './node_manipulation'; import {addRemoveViewFromContainer, appendChild, detachView, findComponentView, getBeforeNodeForView, getHostElementNode, getParentLNode, getParentOrContainerNode, getRenderParent, insertView, removeView} from './node_manipulation';
import {isComponent, loadElementInternal} from './util'; import {getLNode, isComponent} from './util';
import {ViewRef} from './view_ref'; import {ViewRef} from './view_ref';
@ -103,28 +103,32 @@ export function getOrCreateNodeInjector(): LInjector {
ngDevMode && assertPreviousIsParent(); ngDevMode && assertPreviousIsParent();
return getOrCreateNodeInjectorForNode( return getOrCreateNodeInjectorForNode(
getPreviousOrParentNode() as LElementNode | LElementContainerNode | LContainerNode, getPreviousOrParentNode() as LElementNode | LElementContainerNode | LContainerNode,
getPreviousOrParentTNode()); getPreviousOrParentTNode() as TElementNode | TElementContainerNode | TContainerNode,
_getViewData());
} }
/** /**
* Creates (or gets an existing) injector for a given element or container. * Creates (or gets an existing) injector for a given element or container.
* *
* @param node for which an injector should be retrieved / created. * @param node for which an injector should be retrieved / created.
* @param tNode for which an injector should be retrieved / created.
* @param hostView View where the node is stored
* @returns Node injector * @returns Node injector
*/ */
export function getOrCreateNodeInjectorForNode( export function getOrCreateNodeInjectorForNode(
node: LElementNode | LElementContainerNode | LContainerNode, tNode: TNode): LInjector { node: LElementNode | LElementContainerNode | LContainerNode,
tNode: TElementNode | TContainerNode | TElementContainerNode, hostView: LViewData): LInjector {
// TODO: remove LNode arg when nodeInjector refactor is done // TODO: remove LNode arg when nodeInjector refactor is done
const nodeInjector = node.nodeInjector; const nodeInjector = node.nodeInjector;
const parentLNode = getParentOrContainerNode(tNode, node.view); const parentLNode = getParentOrContainerNode(tNode, hostView);
const parentInjector = parentLNode && parentLNode.nodeInjector; const parentInjector = parentLNode && parentLNode.nodeInjector;
if (nodeInjector != parentInjector) { if (nodeInjector != parentInjector) {
return nodeInjector !; return nodeInjector !;
} }
return node.nodeInjector = { return node.nodeInjector = {
parent: parentInjector, parent: parentInjector,
node: node,
tNode: tNode, tNode: tNode,
view: hostView,
bf0: 0, bf0: 0,
bf1: 0, bf1: 0,
bf2: 0, bf2: 0,
@ -306,11 +310,12 @@ export function getOrCreateChangeDetectorRef(
di: LInjector, context: any): viewEngine_ChangeDetectorRef { di: LInjector, context: any): viewEngine_ChangeDetectorRef {
if (di.changeDetectorRef) return di.changeDetectorRef; if (di.changeDetectorRef) return di.changeDetectorRef;
const currentTNode = getPreviousOrParentTNode(); const currentTNode = di.tNode;
if (isComponent(currentTNode)) { if (isComponent(currentTNode)) {
return di.changeDetectorRef = new ViewRef(di.node.data as LViewData, context); return di.changeDetectorRef =
new ViewRef(getLNode(currentTNode, di.view).data as LViewData, context);
} else if (currentTNode.type === TNodeType.Element) { } else if (currentTNode.type === TNodeType.Element) {
return di.changeDetectorRef = getOrCreateHostChangeDetector(_getViewData()); return di.changeDetectorRef = getOrCreateHostChangeDetector(di.view);
} }
return null !; return null !;
} }
@ -326,7 +331,7 @@ function getOrCreateHostChangeDetector(currentView: LViewData): viewEngine_Chang
} }
function getOrCreateRenderer2(di: LInjector): Renderer2 { function getOrCreateRenderer2(di: LInjector): Renderer2 {
const renderer = di.node.view[RENDERER]; const renderer = di.view[RENDERER];
if (isProceduralRenderer(renderer)) { if (isProceduralRenderer(renderer)) {
return renderer as Renderer2; return renderer as Renderer2;
} else { } else {
@ -368,22 +373,22 @@ export function getOrCreateInjectable<T>(
// At this point, we have an injector which *may* contain the token, so we step through the // At this point, we have an injector which *may* contain the token, so we step through the
// directives associated with the injector's corresponding node to get the directive instance. // directives associated with the injector's corresponding node to get the directive instance.
const node = injector.node;
const tNode = injector.tNode; const tNode = injector.tNode;
const injectorView = injector.view;
const nodeFlags = tNode.flags; const nodeFlags = tNode.flags;
const count = nodeFlags & TNodeFlags.DirectiveCountMask; const count = nodeFlags & TNodeFlags.DirectiveCountMask;
if (count !== 0) { if (count !== 0) {
const start = nodeFlags >> TNodeFlags.DirectiveStartingIndexShift; const start = nodeFlags >> TNodeFlags.DirectiveStartingIndexShift;
const end = start + count; const end = start + count;
const defs = node.view[TVIEW].directives !; const defs = injectorView[TVIEW].directives !;
for (let i = start; i < end; i++) { for (let i = start; i < end; i++) {
// Get the definition for the directive at this index and, if it is injectable (diPublic), // Get the definition for the directive at this index and, if it is injectable (diPublic),
// and matches the given token, return the directive instance. // and matches the given token, return the directive instance.
const directiveDef = defs[i] as DirectiveDefInternal<any>; const directiveDef = defs[i] as DirectiveDefInternal<any>;
if (directiveDef.type === token && directiveDef.diPublic) { if (directiveDef.type === token && directiveDef.diPublic) {
return node.view[DIRECTIVES] ![i]; return injectorView[DIRECTIVES] ![i];
} }
} }
} }
@ -392,7 +397,7 @@ export function getOrCreateInjectable<T>(
// injector, it's possible the directive is on this node and hasn't been created yet. // injector, it's possible the directive is on this node and hasn't been created yet.
let instance: T|null; let instance: T|null;
if (injector === nodeInjector && if (injector === nodeInjector &&
(instance = searchMatchesQueuedForCreation<T>(node, token))) { (instance = searchMatchesQueuedForCreation<T>(token, injectorView[TVIEW]))) {
return instance; return instance;
} }
@ -406,7 +411,7 @@ export function getOrCreateInjectable<T>(
} }
} }
const moduleInjector = getPreviousOrParentNode() !.view[INJECTOR]; const moduleInjector = nodeInjector.view[INJECTOR];
const formerInjector = setCurrentInjector(moduleInjector); const formerInjector = setCurrentInjector(moduleInjector);
try { try {
return inject(token, flags); return inject(token, flags);
@ -415,13 +420,13 @@ export function getOrCreateInjectable<T>(
} }
} }
function searchMatchesQueuedForCreation<T>(node: LNode, token: any): T|null { function searchMatchesQueuedForCreation<T>(token: any, hostTView: TView): T|null {
const matches = node.view[TVIEW].currentMatches; const matches = hostTView.currentMatches;
if (matches) { if (matches) {
for (let i = 0; i < matches.length; i += 2) { for (let i = 0; i < matches.length; i += 2) {
const def = matches[i] as DirectiveDefInternal<any>; const def = matches[i] as DirectiveDefInternal<any>;
if (def.type === token) { if (def.type === token) {
return resolveDirective(def, i + 1, matches, node.view[TVIEW]); return resolveDirective(def, i + 1, matches, hostTView);
} }
} }
} }
@ -528,7 +533,7 @@ export function bloomFindPossibleInjector(
* the injector and its parent view don't match because it means we'd cross the view boundary. * the injector and its parent view don't match because it means we'd cross the view boundary.
*/ */
function sameHostView(injector: LInjector): boolean { function sameHostView(injector: LInjector): boolean {
return !!injector.parent && injector.parent.node.view === injector.node.view; return !!injector.parent && injector.parent.view === injector.view;
} }
export class ReadFromInjectorFn<T> { export class ReadFromInjectorFn<T> {
@ -543,7 +548,7 @@ export class ReadFromInjectorFn<T> {
* @returns The ElementRef instance to use * @returns The ElementRef instance to use
*/ */
export function getOrCreateElementRef(di: LInjector): viewEngine_ElementRef { export function getOrCreateElementRef(di: LInjector): viewEngine_ElementRef {
return di.elementRef || (di.elementRef = new ElementRef(di.node.native)); return di.elementRef || (di.elementRef = new ElementRef(getLNode(di.tNode, di.view).native));
} }
export const QUERY_READ_TEMPLATE_REF = <QueryReadType<viewEngine_TemplateRef<any>>>( export const QUERY_READ_TEMPLATE_REF = <QueryReadType<viewEngine_TemplateRef<any>>>(
@ -563,7 +568,7 @@ export const QUERY_READ_FROM_NODE =
ngDevMode && assertNodeOfPossibleTypes( ngDevMode && assertNodeOfPossibleTypes(
tNode, TNodeType.Container, TNodeType.Element, TNodeType.ElementContainer); tNode, TNodeType.Container, TNodeType.Element, TNodeType.ElementContainer);
if (directiveIdx > -1) { if (directiveIdx > -1) {
return _getViewData()[DIRECTIVES] ![directiveIdx]; return injector.view[DIRECTIVES] ![directiveIdx];
} }
if (tNode.type === TNodeType.Element || tNode.type === TNodeType.ElementContainer) { if (tNode.type === TNodeType.Element || tNode.type === TNodeType.ElementContainer) {
return getOrCreateElementRef(injector); return getOrCreateElementRef(injector);
@ -594,11 +599,11 @@ export function getOrCreateContainerRef(di: LInjector): viewEngine_ViewContainer
ngDevMode && assertNodeOfPossibleTypes( ngDevMode && assertNodeOfPossibleTypes(
hostTNode, TNodeType.Container, TNodeType.Element, TNodeType.ElementContainer); hostTNode, TNodeType.Container, TNodeType.Element, TNodeType.ElementContainer);
const hostView = hostLNode.view; const hostView = di.view;
const lContainer = createLContainer(hostView, true); const lContainer = createLContainer(hostView, true);
const comment = hostView[RENDERER].createComment(ngDevMode ? 'container' : ''); const comment = hostView[RENDERER].createComment(ngDevMode ? 'container' : '');
const lContainerNode: LContainerNode = createLNodeObject( const lContainerNode: LContainerNode =
TNodeType.Container, hostView, hostLNode.nodeInjector, comment, lContainer); createLNodeObject(TNodeType.Container, hostLNode.nodeInjector, comment, lContainer);
lContainer[RENDER_PARENT] = getRenderParent(hostTNode, hostView); lContainer[RENDER_PARENT] = getRenderParent(hostTNode, hostView);
@ -613,7 +618,7 @@ export function getOrCreateContainerRef(di: LInjector): viewEngine_ViewContainer
addToViewTree(hostView, hostTNode.index as number, lContainer); addToViewTree(hostView, hostTNode.index as number, lContainer);
di.viewContainerRef = new ViewContainerRef( di.viewContainerRef = new ViewContainerRef(
lContainerNode, hostTNode.dynamicContainerNode as TContainerNode, hostLNode, hostTNode); lContainer, hostTNode.dynamicContainerNode as TContainerNode, hostTNode, hostView);
} }
return di.viewContainerRef; return di.viewContainerRef;
@ -651,49 +656,49 @@ class ViewContainerRef extends viewEngine_ViewContainerRef {
private _viewRefs: viewEngine_ViewRef[] = []; private _viewRefs: viewEngine_ViewRef[] = [];
constructor( constructor(
private _lContainerNode: LContainerNode, private _tContainerNode: TContainerNode, private _lContainer: LContainer, private _tContainerNode: TContainerNode,
private _hostNode: LElementNode|LElementContainerNode|LContainerNode, private _hostTNode: TElementNode|TContainerNode|TElementContainerNode,
private _hostTNode: TNode) { private _hostView: LViewData) {
super(); super();
} }
get element(): ElementRef { get element(): ElementRef {
const injector = getOrCreateNodeInjectorForNode(this._hostNode, this._hostTNode); // TODO: Remove LNode lookup when removing LNode.nodeInjector
const injector =
getOrCreateNodeInjectorForNode(this._getHostNode(), this._hostTNode, this._hostView);
return getOrCreateElementRef(injector); return getOrCreateElementRef(injector);
} }
get injector(): Injector { get injector(): Injector {
const injector = getOrCreateNodeInjectorForNode(this._hostNode, this._hostTNode); // TODO: Remove LNode lookup when removing LNode.nodeInjector
const injector =
getOrCreateNodeInjectorForNode(this._getHostNode(), this._hostTNode, this._hostView);
return new NodeInjector(injector); return new NodeInjector(injector);
} }
/** @deprecated No replacement */ /** @deprecated No replacement */
get parentInjector(): Injector { get parentInjector(): Injector {
const parentLInjector = getParentLNode(this._hostTNode, this._hostNode.view) !.nodeInjector; const parentLInjector = getParentLNode(this._hostTNode, this._hostView) !.nodeInjector;
return parentLInjector ? new NodeInjector(parentLInjector) : new NullInjector(); return parentLInjector ? new NodeInjector(parentLInjector) : new NullInjector();
} }
clear(): void { clear(): void {
const lContainer = this._lContainerNode.data; while (this._lContainer[VIEWS].length) {
while (lContainer[VIEWS].length) {
this.remove(0); this.remove(0);
} }
} }
get(index: number): viewEngine_ViewRef|null { return this._viewRefs[index] || null; } get(index: number): viewEngine_ViewRef|null { return this._viewRefs[index] || null; }
get length(): number { get length(): number { return this._lContainer[VIEWS].length; }
const lContainer = this._lContainerNode.data;
return lContainer[VIEWS].length;
}
createEmbeddedView<C>(templateRef: viewEngine_TemplateRef<C>, context?: C, index?: number): createEmbeddedView<C>(templateRef: viewEngine_TemplateRef<C>, context?: C, index?: number):
viewEngine_EmbeddedViewRef<C> { viewEngine_EmbeddedViewRef<C> {
const adjustedIdx = this._adjustIndex(index); const adjustedIdx = this._adjustIndex(index);
const viewRef = const viewRef = (templateRef as TemplateRef<C>)
(templateRef as TemplateRef<C>) .createEmbeddedView(
.createEmbeddedView( context || <any>{}, this._lContainer, this._tContainerNode,
context || <any>{}, this._lContainerNode, this._tContainerNode, adjustedIdx); this._hostView, adjustedIdx);
(viewRef as ViewRef<any>).attachToViewContainerRef(this); (viewRef as ViewRef<any>).attachToViewContainerRef(this);
this._viewRefs.splice(adjustedIdx, 0, viewRef); this._viewRefs.splice(adjustedIdx, 0, viewRef);
return viewRef; return viewRef;
@ -721,9 +726,11 @@ class ViewContainerRef extends viewEngine_ViewContainerRef {
const lView = (viewRef as ViewRef<any>)._view !; const lView = (viewRef as ViewRef<any>)._view !;
const adjustedIdx = this._adjustIndex(index); const adjustedIdx = this._adjustIndex(index);
insertView(this._lContainerNode, lView, adjustedIdx, this._tContainerNode.parent !.index); insertView(
const beforeNode = lView, this._lContainer, this._hostView, adjustedIdx, this._tContainerNode.parent !.index);
getBeforeNodeForView(adjustedIdx, this._lContainerNode.data[VIEWS], this._lContainerNode);
const container = this._getHostNode().dynamicLContainerNode !;
const beforeNode = getBeforeNodeForView(adjustedIdx, this._lContainer[VIEWS], container);
addRemoveViewFromContainer(lView, true, beforeNode); addRemoveViewFromContainer(lView, true, beforeNode);
(viewRef as ViewRef<any>).attachToViewContainerRef(this); (viewRef as ViewRef<any>).attachToViewContainerRef(this);
@ -743,27 +750,29 @@ class ViewContainerRef extends viewEngine_ViewContainerRef {
remove(index?: number): void { remove(index?: number): void {
const adjustedIdx = this._adjustIndex(index, -1); const adjustedIdx = this._adjustIndex(index, -1);
removeView(this._lContainerNode, this._tContainerNode as TContainerNode, adjustedIdx); removeView(this._lContainer, this._tContainerNode as TContainerNode, adjustedIdx);
this._viewRefs.splice(adjustedIdx, 1); this._viewRefs.splice(adjustedIdx, 1);
} }
detach(index?: number): viewEngine_ViewRef|null { detach(index?: number): viewEngine_ViewRef|null {
const adjustedIdx = this._adjustIndex(index, -1); const adjustedIdx = this._adjustIndex(index, -1);
detachView(this._lContainerNode, adjustedIdx, !!this._tContainerNode.detached); detachView(this._lContainer, adjustedIdx, !!this._tContainerNode.detached);
return this._viewRefs.splice(adjustedIdx, 1)[0] || null; return this._viewRefs.splice(adjustedIdx, 1)[0] || null;
} }
private _adjustIndex(index?: number, shift: number = 0) { private _adjustIndex(index?: number, shift: number = 0) {
if (index == null) { if (index == null) {
return this._lContainerNode.data[VIEWS].length + shift; return this._lContainer[VIEWS].length + shift;
} }
if (ngDevMode) { if (ngDevMode) {
assertGreaterThan(index, -1, 'index must be positive'); assertGreaterThan(index, -1, 'index must be positive');
// +1 because it's legal to insert at the end. // +1 because it's legal to insert at the end.
assertLessThan(index, this._lContainerNode.data[VIEWS].length + 1 + shift, 'index'); assertLessThan(index, this._lContainer[VIEWS].length + 1 + shift, 'index');
} }
return index; return index;
} }
private _getHostNode() { return getLNode(this._hostTNode, this._hostView); }
} }
/** /**
@ -780,7 +789,7 @@ export function getOrCreateTemplateRef<T>(di: LInjector): viewEngine_TemplateRef
ngDevMode && assertNodeType(hostTNode, TNodeType.Container); ngDevMode && assertNodeType(hostTNode, TNodeType.Container);
ngDevMode && assertDefined(hostTNode.tViews, 'TView must be allocated'); ngDevMode && assertDefined(hostTNode.tViews, 'TView must be allocated');
di.templateRef = new TemplateRef<any>( di.templateRef = new TemplateRef<any>(
hostNode.view, getOrCreateElementRef(di), hostTNode.tViews as TView, getRenderer(), di.view, getOrCreateElementRef(di), hostTNode.tViews as TView, getRenderer(),
hostNode.data ![QUERIES]); hostNode.data ![QUERIES]);
} }
return di.templateRef; return di.templateRef;
@ -818,12 +827,12 @@ class TemplateRef<T> extends viewEngine_TemplateRef<T> {
} }
createEmbeddedView( createEmbeddedView(
context: T, containerNode?: LContainerNode, tContainerNode?: TContainerNode, context: T, container?: LContainer, tContainerNode?: TContainerNode, hostView?: LViewData,
index?: number): viewEngine_EmbeddedViewRef<T> { index?: number): viewEngine_EmbeddedViewRef<T> {
const lView = createEmbeddedViewAndNode( const lView = createEmbeddedViewAndNode(
this._tView, context, this._declarationParentView, this._renderer, this._queries); this._tView, context, this._declarationParentView, this._renderer, this._queries);
if (containerNode) { if (container) {
insertView(containerNode, lView, index !, tContainerNode !.parent !.index); insertView(lView, container, hostView !, index !, tContainerNode !.parent !.index);
} }
renderEmbeddedTemplate(lView, this._tView, context, RenderFlags.Create); renderEmbeddedTemplate(lView, this._tView, context, RenderFlags.Create);
const viewRef = new ViewRef(lView, context); const viewRef = new ViewRef(lView, context);
@ -836,6 +845,8 @@ class TemplateRef<T> extends viewEngine_TemplateRef<T> {
* Retrieves `TemplateRef` instance from `Injector` when a local reference is placed on the * Retrieves `TemplateRef` instance from `Injector` when a local reference is placed on the
* `<ng-template>` element. * `<ng-template>` element.
*/ */
export function templateRefExtractor(lNode: LNodeWithLocalRefs, tNode: TNode) { export function templateRefExtractor(tNode: TContainerNode, currentView: LViewData) {
return getOrCreateTemplateRef(getOrCreateNodeInjectorForNode(lNode, tNode)); // TODO: remove this lookup with removing LNode.nodeInjector
const lNode = getLNode(tNode, currentView) as LContainerNode;
return getOrCreateTemplateRef(getOrCreateNodeInjectorForNode(lNode, tNode, currentView));
} }

View File

@ -256,7 +256,7 @@ function appendI18nNode(
const viewData = _getViewData(); const viewData = _getViewData();
// On first pass, re-organize node tree to put this node in the correct position. // On first pass, re-organize node tree to put this node in the correct position.
const firstTemplatePass = node.view[TVIEW].firstTemplatePass; const firstTemplatePass = viewData[TVIEW].firstTemplatePass;
if (firstTemplatePass) { if (firstTemplatePass) {
if (previousTNode === parentTNode && tNode !== parentTNode.child) { if (previousTNode === parentTNode && tNode !== parentTNode.child) {
tNode.next = parentTNode.child; tNode.next = parentTNode.child;

View File

@ -19,16 +19,16 @@ import {executeHooks, executeInitHooks, queueInitHooks, queueLifecycleHooks} fro
import {ACTIVE_INDEX, LContainer, RENDER_PARENT, VIEWS} from './interfaces/container'; import {ACTIVE_INDEX, LContainer, RENDER_PARENT, VIEWS} from './interfaces/container';
import {ComponentDefInternal, ComponentQuery, ComponentTemplate, DirectiveDefInternal, DirectiveDefListOrFactory, InitialStylingFlags, PipeDefListOrFactory, RenderFlags} from './interfaces/definition'; import {ComponentDefInternal, ComponentQuery, ComponentTemplate, DirectiveDefInternal, DirectiveDefListOrFactory, InitialStylingFlags, PipeDefListOrFactory, RenderFlags} from './interfaces/definition';
import {LInjector} from './interfaces/injector'; import {LInjector} from './interfaces/injector';
import {AttributeMarker, InitialInputData, InitialInputs, LContainerNode, LElementNode, LNode, LNodeWithLocalRefs, LProjectionNode, LTextNode, LViewNode, LocalRefExtractor, PropertyAliasValue, PropertyAliases, TAttributes, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeType, TProjectionNode, TViewNode} from './interfaces/node'; import {AttributeMarker, InitialInputData, InitialInputs, LContainerNode, LElementContainerNode, LElementNode, LNode, LProjectionNode, LTextNode, LViewNode, LocalRefExtractor, PropertyAliasValue, PropertyAliases, TAttributes, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeType, TProjectionNode, TViewNode} from './interfaces/node';
import {CssSelectorList, NG_PROJECT_AS_ATTR_NAME} from './interfaces/projection'; import {CssSelectorList, NG_PROJECT_AS_ATTR_NAME} from './interfaces/projection';
import {LQueries} from './interfaces/query'; import {LQueries} from './interfaces/query';
import {ProceduralRenderer3, RComment, RElement, RNode, RText, Renderer3, RendererFactory3, isProceduralRenderer} from './interfaces/renderer'; import {ProceduralRenderer3, RComment, RElement, RNode, RText, Renderer3, RendererFactory3, isProceduralRenderer} from './interfaces/renderer';
import {BINDING_INDEX, CLEANUP, CONTAINER_INDEX, CONTENT_QUERIES, CONTEXT, CurrentMatchesList, DECLARATION_VIEW, DIRECTIVES, FLAGS, HEADER_OFFSET, HOST_NODE, INJECTOR, LViewData, LViewFlags, NEXT, OpaqueViewState, PARENT, QUERIES, RENDERER, RootContext, SANITIZER, TAIL, TVIEW, TView} from './interfaces/view'; import {BINDING_INDEX, CLEANUP, CONTAINER_INDEX, CONTENT_QUERIES, CONTEXT, CurrentMatchesList, DECLARATION_VIEW, DIRECTIVES, FLAGS, HEADER_OFFSET, HOST_NODE, INJECTOR, LViewData, LViewFlags, NEXT, OpaqueViewState, PARENT, QUERIES, RENDERER, RootContext, SANITIZER, TAIL, TVIEW, TView} from './interfaces/view';
import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert'; import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert';
import {appendChild, appendProjectedNode, createTextNode, findComponentView, getContainerNode, getHostElementNode, getLViewChild, getParentLNode, getParentOrContainerNode, getRenderParent, insertView, removeView} from './node_manipulation'; import {appendChild, appendProjectedNode, createTextNode, findComponentView, getContainerNode, getHostElementNode, getLViewChild, getParentOrContainerNode, getRenderParent, insertView, removeView} from './node_manipulation';
import {isNodeMatchingSelectorList, matchingSelectorIndex} from './node_selector_matcher'; import {isNodeMatchingSelectorList, matchingSelectorIndex} from './node_selector_matcher';
import {StylingContext, allocStylingContext, createStylingContextTemplate, renderStyling as renderElementStyles, updateClassProp as updateElementClassProp, updateStyleProp as updateElementStyleProp, updateStylingMap} from './styling'; import {StylingContext, allocStylingContext, createStylingContextTemplate, renderStyling as renderElementStyles, updateClassProp as updateElementClassProp, updateStyleProp as updateElementStyleProp, updateStylingMap} from './styling';
import {assertDataInRangeInternal, isContentQueryHost, isDifferent, loadElementInternal, loadInternal, readElementValue, stringify} from './util'; import {assertDataInRangeInternal, getLNode, isContentQueryHost, isDifferent, loadElementInternal, loadInternal, readElementValue, stringify} from './util';
import {ViewRef} from './view_ref'; import {ViewRef} from './view_ref';
@ -132,7 +132,7 @@ let previousOrParentTNode: TNode;
export function getPreviousOrParentNode(): LNode|null { export function getPreviousOrParentNode(): LNode|null {
return previousOrParentTNode == null || previousOrParentTNode === viewData[HOST_NODE] ? return previousOrParentTNode == null || previousOrParentTNode === viewData[HOST_NODE] ?
getHostElementNode(viewData) : getHostElementNode(viewData) :
readElementValue(viewData[previousOrParentTNode.index]); getLNode(previousOrParentTNode, viewData);
} }
export function getPreviousOrParentTNode(): TNode { export function getPreviousOrParentTNode(): TNode {
@ -393,12 +393,10 @@ export function createLViewData<T>(
* (same properties assigned in the same order). * (same properties assigned in the same order).
*/ */
export function createLNodeObject( export function createLNodeObject(
type: TNodeType, currentView: LViewData, nodeInjector: LInjector | null, type: TNodeType, nodeInjector: LInjector | null, native: RText | RElement | RComment | null,
native: RText | RElement | RComment | null,
state: any): LElementNode&LTextNode&LViewNode&LContainerNode&LProjectionNode { state: any): LElementNode&LTextNode&LViewNode&LContainerNode&LProjectionNode {
return { return {
native: native as any, native: native as any,
view: currentView,
nodeInjector: nodeInjector, nodeInjector: nodeInjector,
data: state, data: state,
dynamicLContainerNode: null dynamicLContainerNode: null
@ -445,7 +443,7 @@ export function createNodeAtIndex(
const tParent = parentInSameView ? parent as TElementNode | TContainerNode : null; const tParent = parentInSameView ? parent as TElementNode | TContainerNode : null;
const isState = state != null; const isState = state != null;
const node = createLNodeObject(type, viewData, null, native, isState ? state as any : null); const node = createLNodeObject(type, null, native, isState ? state as any : null);
let tNode: TNode; let tNode: TNode;
if (index === -1 || type === TNodeType.View) { if (index === -1 || type === TNodeType.View) {
@ -780,7 +778,8 @@ export function elementContainerEnd(): void {
} }
ngDevMode && assertNodeType(previousOrParentTNode, TNodeType.ElementContainer); ngDevMode && assertNodeType(previousOrParentTNode, TNodeType.ElementContainer);
currentQueries && (currentQueries = currentQueries.addNode(previousOrParentTNode)); currentQueries &&
(currentQueries = currentQueries.addNode(previousOrParentTNode as TElementContainerNode));
queueLifecycleHooks(previousOrParentTNode.flags, tView); queueLifecycleHooks(previousOrParentTNode.flags, tView);
} }
@ -848,8 +847,8 @@ export function elementCreate(name: string, overriddenRenderer?: Renderer3): REl
return native; return native;
} }
function nativeNodeLocalRefExtractor(lNode: LNodeWithLocalRefs, tNode: TNode): RNode { function nativeNodeLocalRefExtractor(tNode: TNode, currentView: LViewData): RNode {
return lNode.native; return getLNode(tNode, currentView).native;
} }
/** /**
@ -1018,13 +1017,12 @@ function saveNameToExportMap(
*/ */
function saveResolvedLocalsInData(localRefExtractor: LocalRefExtractor): void { function saveResolvedLocalsInData(localRefExtractor: LocalRefExtractor): void {
const localNames = previousOrParentTNode.localNames; const localNames = previousOrParentTNode.localNames;
const node = getPreviousOrParentNode() as LElementNode; const tNode = previousOrParentTNode as TElementNode | TContainerNode | TElementContainerNode;
if (localNames) { if (localNames) {
let localIndex = previousOrParentTNode.index + 1; let localIndex = previousOrParentTNode.index + 1;
for (let i = 0; i < localNames.length; i += 2) { for (let i = 0; i < localNames.length; i += 2) {
const index = localNames[i + 1] as number; const index = localNames[i + 1] as number;
const value = const value = index === -1 ? localRefExtractor(tNode, viewData) : directives ![index];
index === -1 ? localRefExtractor(node, previousOrParentTNode) : directives ![index];
viewData[localIndex++] = value; viewData[localIndex++] = value;
} }
} }
@ -1206,7 +1204,6 @@ export function hostElement(
if (def.diPublic) def.diPublic(def); if (def.diPublic) def.diPublic(def);
tView.directives = [def]; tView.directives = [def];
} }
return viewData[HEADER_OFFSET]; return viewData[HEADER_OFFSET];
} }
@ -1316,7 +1313,8 @@ export function elementEnd(): void {
previousOrParentTNode = previousOrParentTNode.parent !; previousOrParentTNode = previousOrParentTNode.parent !;
} }
ngDevMode && assertNodeType(previousOrParentTNode, TNodeType.Element); ngDevMode && assertNodeType(previousOrParentTNode, TNodeType.Element);
currentQueries && (currentQueries = currentQueries.addNode(previousOrParentTNode)); currentQueries &&
(currentQueries = currentQueries.addNode(previousOrParentTNode as TElementNode));
queueLifecycleHooks(previousOrParentTNode.flags, tView); queueLifecycleHooks(previousOrParentTNode.flags, tView);
elementDepthCount--; elementDepthCount--;
@ -1923,7 +1921,8 @@ export function template(
} }
createDirectivesAndLocals(localRefs, localRefExtractor); createDirectivesAndLocals(localRefs, localRefExtractor);
currentQueries && (currentQueries = currentQueries.addNode(previousOrParentTNode)); currentQueries &&
(currentQueries = currentQueries.addNode(previousOrParentTNode as TContainerNode));
queueLifecycleHooks(tNode.flags, tView); queueLifecycleHooks(tNode.flags, tView);
isParent = false; isParent = false;
} }
@ -2004,14 +2003,15 @@ export function containerRefreshEnd(): void {
previousOrParentTNode = previousOrParentTNode.parent !; previousOrParentTNode = previousOrParentTNode.parent !;
} }
// Inline containers cannot have style bindings, so we can read the value directly
const container = viewData[previousOrParentTNode.index];
ngDevMode && assertNodeType(previousOrParentTNode, TNodeType.Container); ngDevMode && assertNodeType(previousOrParentTNode, TNodeType.Container);
const nextIndex = container.data[ACTIVE_INDEX] !;
// Inline containers cannot have style bindings, so we can read the value directly
const lContainer = viewData[previousOrParentTNode.index].data;
const nextIndex = lContainer[ACTIVE_INDEX];
// remove extra views at the end of the container // remove extra views at the end of the container
while (nextIndex < container.data[VIEWS].length) { while (nextIndex < lContainer[VIEWS].length) {
removeView(container, previousOrParentTNode as TContainerNode, nextIndex); removeView(lContainer, previousOrParentTNode as TContainerNode, nextIndex);
} }
} }
@ -2043,22 +2043,23 @@ function refreshDynamicEmbeddedViews(lViewData: LViewData) {
* Looks for a view with a given view block id inside a provided LContainer. * Looks for a view with a given view block id inside a provided LContainer.
* Removes views that need to be deleted in the process. * Removes views that need to be deleted in the process.
* *
* @param containerNode where to search for views * @param lContainer to search for views
* @param tContainerNode to search for views
* @param startIdx starting index in the views array to search from * @param startIdx starting index in the views array to search from
* @param viewBlockId exact view block id to look for * @param viewBlockId exact view block id to look for
* @returns index of a found view or -1 if not found * @returns index of a found view or -1 if not found
*/ */
function scanForView( function scanForView(
containerNode: LContainerNode, tContainerNode: TContainerNode, startIdx: number, lContainer: LContainer, tContainerNode: TContainerNode, startIdx: number,
viewBlockId: number): LViewData|null { viewBlockId: number): LViewData|null {
const views = containerNode.data[VIEWS]; const views = lContainer[VIEWS];
for (let i = startIdx; i < views.length; i++) { for (let i = startIdx; i < views.length; i++) {
const viewAtPositionId = views[i][TVIEW].id; const viewAtPositionId = views[i][TVIEW].id;
if (viewAtPositionId === viewBlockId) { if (viewAtPositionId === viewBlockId) {
return views[i]; return views[i];
} else if (viewAtPositionId < viewBlockId) { } else if (viewAtPositionId < viewBlockId) {
// found a view that should not be at this position - remove // found a view that should not be at this position - remove
removeView(containerNode, tContainerNode, i); removeView(lContainer, tContainerNode, i);
} else { } else {
// found a view with id greater than the one we are searching for // found a view with id greater than the one we are searching for
// which means that required view doesn't exist and can't be found at // which means that required view doesn't exist and can't be found at
@ -2082,11 +2083,12 @@ export function embeddedViewStart(viewBlockId: number, consts: number, vars: num
previousOrParentTNode; previousOrParentTNode;
// Inline containers cannot have style bindings, so we can read the value directly // Inline containers cannot have style bindings, so we can read the value directly
const container = viewData[containerTNode.index] as LContainerNode; const container = viewData[containerTNode.index] as LContainerNode;
const currentView = viewData;
ngDevMode && assertNodeType(containerTNode, TNodeType.Container); ngDevMode && assertNodeType(containerTNode, TNodeType.Container);
const lContainer = container.data; const lContainer = container.data;
let viewToRender = scanForView( let viewToRender = scanForView(
container, containerTNode as TContainerNode, lContainer[ACTIVE_INDEX] !, viewBlockId); lContainer, containerTNode as TContainerNode, lContainer[ACTIVE_INDEX] !, viewBlockId);
if (viewToRender) { if (viewToRender) {
isParent = true; isParent = true;
@ -2108,7 +2110,7 @@ export function embeddedViewStart(viewBlockId: number, consts: number, vars: num
if (container) { if (container) {
if (creationMode) { if (creationMode) {
// it is a new view, insert it into collection of views for a given container // it is a new view, insert it into collection of views for a given container
insertView(container, viewToRender, lContainer[ACTIVE_INDEX] !, -1); insertView(viewToRender, lContainer, currentView, lContainer[ACTIVE_INDEX] !, -1);
} }
lContainer[ACTIVE_INDEX] !++; lContainer[ACTIVE_INDEX] !++;
} }
@ -2846,11 +2848,4 @@ function assertDataNext(index: number, arr?: any[]) {
arr.length, index, `index ${index} expected to be at the end of arr (length ${arr.length})`); arr.length, index, `index ${index} expected to be at the end of arr (length ${arr.length})`);
} }
export function _getComponentHostLElementNode(component: any): LElementNode {
ngDevMode && assertDefined(component, 'expecting component got null');
const lElementNode = getLElementFromComponent(component) !;
ngDevMode && assertDefined(component, 'object is not a component');
return lElementNode;
}
export const CLEAN_PROMISE = _CLEAN_PROMISE; export const CLEAN_PROMISE = _CLEAN_PROMISE;

View File

@ -6,12 +6,14 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {ChangeDetectorRef} from '../../change_detection/change_detector_ref'; import {ChangeDetectorRef} from '../../change_detection/change_detector_ref';
import {ElementRef} from '../../linker/element_ref'; import {ElementRef} from '../../linker/element_ref';
import {TemplateRef} from '../../linker/template_ref'; import {TemplateRef} from '../../linker/template_ref';
import {ViewContainerRef} from '../../linker/view_container_ref'; import {ViewContainerRef} from '../../linker/view_container_ref';
import {LContainerNode, LElementContainerNode, LElementNode, TContainerNode, TElementNode, TNode} from './node'; import {TContainerNode, TElementContainerNode, TElementNode,} from './node';
import {LViewData} from './view';
export interface LInjector { export interface LInjector {
/** /**
@ -20,15 +22,14 @@ export interface LInjector {
*/ */
readonly parent: LInjector|null; readonly parent: LInjector|null;
/** /** Necessary to find directive indices for a particular node and look up the LNode. */
* Allows access to the directives array in that node's static data and to readonly tNode: TElementNode|TElementContainerNode|TContainerNode;
* the node's flags (for starting directive index and directive size). Necessary
* for DI to retrieve a directive from the data array if injector indicates
* it is there.
*/
readonly node: LElementNode|LElementContainerNode|LContainerNode;
readonly tNode: TNode; /**
* The view where the node is stored. Necessary because as we traverse up the injector
* tree the view where we search directives may change.
*/
readonly view: LViewData;
/** /**
* The following bloom filter determines whether a directive is available * The following bloom filter determines whether a directive is available

View File

@ -81,13 +81,6 @@ export interface LNode {
*/ */
readonly data: LViewData|LContainer|null; readonly data: LViewData|LContainer|null;
/**
* Each node belongs to a view.
*
* When the injector is walking up a tree, it needs access to the `directives` (part of view).
*/
readonly view: LViewData;
/** The injector associated with this node. Necessary for DI. */ /** The injector associated with this node. Necessary for DI. */
nodeInjector: LInjector|null; nodeInjector: LInjector|null;
@ -530,9 +523,9 @@ export type InitialInputs = string[];
export const unusedValueExportToPlacateAjd = 1; export const unusedValueExportToPlacateAjd = 1;
/** /**
* Type representing a set of LNodes that can have local refs (`#foo`) placed on them. * Type representing a set of TNodes that can have local refs (`#foo`) placed on them.
*/ */
export type LNodeWithLocalRefs = LContainerNode | LElementNode | LElementContainerNode; export type TNodeWithLocalRefs = TContainerNode | TElementNode | TElementContainerNode;
/** /**
* Type for a function that extracts a value for a local refs. * Type for a function that extracts a value for a local refs.
@ -540,4 +533,4 @@ export type LNodeWithLocalRefs = LContainerNode | LElementNode | LElementContain
* - `<div #nativeDivEl>` - `nativeDivEl` should point to the native `<div>` element; * - `<div #nativeDivEl>` - `nativeDivEl` should point to the native `<div>` element;
* - `<ng-template #tplRef>` - `tplRef` should point to the `TemplateRef` instance; * - `<ng-template #tplRef>` - `tplRef` should point to the `TemplateRef` instance;
*/ */
export type LocalRefExtractor = (lNode: LNodeWithLocalRefs, tNode: TNode) => any; export type LocalRefExtractor = (tNode: TNodeWithLocalRefs, currentView: LViewData) => any;

View File

@ -8,7 +8,7 @@
import {QueryList} from '../../linker'; import {QueryList} from '../../linker';
import {Type} from '../../type'; import {Type} from '../../type';
import {TNode} from './node'; import {TContainerNode, TElementContainerNode, TElementNode, TNode} from './node';
/** Used for tracking queries (e.g. ViewChild, ContentChild). */ /** Used for tracking queries (e.g. ViewChild, ContentChild). */
export interface LQueries { export interface LQueries {
@ -33,7 +33,7 @@ export interface LQueries {
* Notify `LQueries` that a new `TNode` has been created and needs to be added to query results * Notify `LQueries` that a new `TNode` has been created and needs to be added to query results
* if matching query predicate. * if matching query predicate.
*/ */
addNode(tNode: TNode): LQueries|null; addNode(tNode: TElementNode|TContainerNode|TElementContainerNode): LQueries|null;
/** /**
* Notify `LQueries` that a new LContainer was added to ivy data structures. As a result we need * Notify `LQueries` that a new LContainer was added to ivy data structures. As a result we need

View File

@ -10,12 +10,12 @@ import {assertDefined} from './assert';
import {attachPatchData} from './context_discovery'; import {attachPatchData} from './context_discovery';
import {callHooks} from './hooks'; import {callHooks} from './hooks';
import {LContainer, RENDER_PARENT, VIEWS, unusedValueExportToPlacateAjd as unused1} from './interfaces/container'; import {LContainer, RENDER_PARENT, VIEWS, unusedValueExportToPlacateAjd as unused1} from './interfaces/container';
import {LContainerNode, LElementContainerNode, LElementNode, LTextNode, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeType, TProjectionNode, TTextNode, TViewNode, unusedValueExportToPlacateAjd as unused2} from './interfaces/node'; import {LContainerNode, LElementContainerNode, LElementNode, LTextNode, TContainerNode, TElementNode, TNode, TNodeFlags, TNodeType, TViewNode, unusedValueExportToPlacateAjd as unused2} from './interfaces/node';
import {unusedValueExportToPlacateAjd as unused3} from './interfaces/projection'; import {unusedValueExportToPlacateAjd as unused3} from './interfaces/projection';
import {ProceduralRenderer3, RComment, RElement, RNode, RText, Renderer3, isProceduralRenderer, unusedValueExportToPlacateAjd as unused4} from './interfaces/renderer'; import {ProceduralRenderer3, RComment, RElement, RNode, RText, Renderer3, isProceduralRenderer, unusedValueExportToPlacateAjd as unused4} from './interfaces/renderer';
import {CLEANUP, CONTAINER_INDEX, DIRECTIVES, FLAGS, HEADER_OFFSET, HOST_NODE, HookData, LViewData, LViewFlags, NEXT, PARENT, QUERIES, RENDERER, TVIEW, unusedValueExportToPlacateAjd as unused5} from './interfaces/view'; import {CLEANUP, CONTAINER_INDEX, 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 {assertNodeType} from './node_assert';
import {isComponent, readElementValue, stringify} from './util'; import {getLNode, readElementValue, stringify} from './util';
const unusedValueToPlacateAjd = unused1 + unused2 + unused3 + unused4 + unused5; const unusedValueToPlacateAjd = unused1 + unused2 + unused3 + unused4 + unused5;
@ -23,7 +23,7 @@ const unusedValueToPlacateAjd = unused1 + unused2 + unused3 + unused4 + unused5;
export function getParentLNode(tNode: TNode, currentView: LViewData): LElementNode| export function getParentLNode(tNode: TNode, currentView: LViewData): LElementNode|
LElementContainerNode|LContainerNode|null { LElementContainerNode|LContainerNode|null {
return tNode.parent == null ? getHostElementNode(currentView) : return tNode.parent == null ? getHostElementNode(currentView) :
readElementValue(currentView[tNode.parent.index]); getLNode(tNode.parent, currentView);
} }
/** /**
@ -33,7 +33,7 @@ export function getParentLNode(tNode: TNode, currentView: LViewData): LElementNo
export function getHostElementNode(currentView: LViewData): LElementNode|null { export function getHostElementNode(currentView: LViewData): LElementNode|null {
const hostTNode = currentView[HOST_NODE] as TElementNode; const hostTNode = currentView[HOST_NODE] as TElementNode;
return hostTNode && hostTNode.type !== TNodeType.View ? return hostTNode && hostTNode.type !== TNodeType.View ?
readElementValue(currentView[PARENT] ![hostTNode.index]) : (getLNode(hostTNode, currentView[PARENT] !) as LElementNode) :
null; null;
} }
@ -117,7 +117,7 @@ function walkTNodeTree(
let nextTNode: TNode|null = null; let nextTNode: TNode|null = null;
const parent = renderParentNode ? renderParentNode.native : null; const parent = renderParentNode ? renderParentNode.native : null;
if (tNode.type === TNodeType.Element) { if (tNode.type === TNodeType.Element) {
const elementNode = readElementValue(currentView ![tNode.index]); const elementNode = getLNode(tNode, currentView);
executeNodeAction(action, renderer, parent, elementNode.native !, beforeNode); executeNodeAction(action, renderer, parent, elementNode.native !, beforeNode);
if (elementNode.dynamicLContainerNode) { if (elementNode.dynamicLContainerNode) {
executeNodeAction( executeNodeAction(
@ -327,15 +327,16 @@ export function destroyViewTree(rootView: LViewData): void {
* root node of another view (in that case, the view's elements will be added when * root node of another view (in that case, the view's elements will be added when
* the container's parent view is added later). * the container's parent view is added later).
* *
* @param container The container into which the view should be inserted * @param lView The view to insert
* @param viewNode The view to insert * @param lContainer The container into which the view should be inserted
* @param parentView The new parent of the inserted view
* @param index The index at which to insert the view * @param index The index at which to insert the view
* @returns The inserted view * @param containerIndex The index of the container node, if dynamic
*/ */
export function insertView( export function insertView(
container: LContainerNode, lView: LViewData, index: number, containerIndex: number) { lView: LViewData, lContainer: LContainer, parentView: LViewData, index: number,
const state = container.data; containerIndex: number) {
const views = state[VIEWS]; const views = lContainer[VIEWS];
if (index > 0) { if (index > 0) {
// This is a new view, we need to add it to the children. // This is a new view, we need to add it to the children.
@ -354,7 +355,7 @@ export function insertView(
// possible to jump from a view to its container's next when walking the node tree. // possible to jump from a view to its container's next when walking the node tree.
if (containerIndex > -1) { if (containerIndex > -1) {
lView[CONTAINER_INDEX] = containerIndex; lView[CONTAINER_INDEX] = containerIndex;
lView[PARENT] = container.view; lView[PARENT] = parentView;
} }
// Notify query that a new view has been added // Notify query that a new view has been added
@ -372,12 +373,12 @@ export function insertView(
* This method splices the view from the container's array of active views. It also * This method splices the view from the container's array of active views. It also
* removes the view's elements from the DOM. * removes the view's elements from the DOM.
* *
* @param container The container from which to detach a view * @param lContainer The container from which to detach a view
* @param removeIndex The index of the view to detach * @param removeIndex The index of the view to detach
* @returns The detached view * @param detached Whether or not this view is already detached.
*/ */
export function detachView(container: LContainerNode, removeIndex: number, detached: boolean) { export function detachView(lContainer: LContainer, removeIndex: number, detached: boolean) {
const views = container.data[VIEWS]; const views = lContainer[VIEWS];
const viewToDetach = views[removeIndex]; const viewToDetach = views[removeIndex];
if (removeIndex > 0) { if (removeIndex > 0) {
views[removeIndex - 1][NEXT] = viewToDetach[NEXT] as LViewData; views[removeIndex - 1][NEXT] = viewToDetach[NEXT] as LViewData;
@ -399,15 +400,15 @@ export function detachView(container: LContainerNode, removeIndex: number, detac
/** /**
* Removes a view from a container, i.e. detaches it and then destroys the underlying LView. * Removes a view from a container, i.e. detaches it and then destroys the underlying LView.
* *
* @param container The container from which to remove a view * @param lContainer The container from which to remove a view
* @param tContainer The TContainer node associated with the LContainer
* @param removeIndex The index of the view to remove * @param removeIndex The index of the view to remove
* @returns The removed view
*/ */
export function removeView( export function removeView(
container: LContainerNode, tContainer: TContainerNode, removeIndex: number) { lContainer: LContainer, tContainer: TContainerNode, removeIndex: number) {
const view = container.data[VIEWS][removeIndex]; const view = lContainer[VIEWS][removeIndex];
destroyLView(view); destroyLView(view);
detachView(container, removeIndex, !!tContainer.detached); detachView(lContainer, removeIndex, !!tContainer.detached);
} }
/** Gets the child of the given LViewData */ /** Gets the child of the given LViewData */
@ -680,8 +681,7 @@ export function getBeforeNodeForView(index: number, views: LViewData[], containe
if (index + 1 < views.length) { if (index + 1 < views.length) {
const view = views[index + 1] as LViewData; const view = views[index + 1] as LViewData;
const viewTNode = view[HOST_NODE] as TViewNode; const viewTNode = view[HOST_NODE] as TViewNode;
return viewTNode.child ? readElementValue(view[viewTNode.child.index]).native : return viewTNode.child ? getLNode(viewTNode.child, view).native : container.native;
container.native;
} else { } else {
return container.native; return container.native;
} }
@ -745,7 +745,7 @@ export function appendProjectedNode(
} else if (projectedTNode.type === TNodeType.ElementContainer) { } else if (projectedTNode.type === TNodeType.ElementContainer) {
let ngContainerChildTNode: TNode|null = projectedTNode.child as TNode; let ngContainerChildTNode: TNode|null = projectedTNode.child as TNode;
while (ngContainerChildTNode) { while (ngContainerChildTNode) {
let ngContainerChild = readElementValue(projectionView[ngContainerChildTNode.index]); let ngContainerChild = getLNode(ngContainerChildTNode, projectionView);
appendProjectedNode( appendProjectedNode(
ngContainerChild as LElementNode | LElementContainerNode | LTextNode | LContainerNode, ngContainerChild as LElementNode | LElementContainerNode | LTextNode | LContainerNode,
ngContainerChildTNode, tProjectionNode, currentView, projectionView); ngContainerChildTNode, tProjectionNode, currentView, projectionView);

View File

@ -20,10 +20,10 @@ import {ReadFromInjectorFn, getOrCreateNodeInjectorForNode} from './di';
import {_getViewData, assertPreviousIsParent, getOrCreateCurrentQueries, store, storeCleanupWithContext} from './instructions'; import {_getViewData, assertPreviousIsParent, getOrCreateCurrentQueries, store, storeCleanupWithContext} from './instructions';
import {DirectiveDefInternal, unusedValueExportToPlacateAjd as unused1} from './interfaces/definition'; import {DirectiveDefInternal, unusedValueExportToPlacateAjd as unused1} from './interfaces/definition';
import {LInjector, unusedValueExportToPlacateAjd as unused2} from './interfaces/injector'; import {LInjector, unusedValueExportToPlacateAjd as unused2} from './interfaces/injector';
import {LContainerNode, LElementNode, TNode, TNodeFlags, unusedValueExportToPlacateAjd as unused3} from './interfaces/node'; import {LContainerNode, LElementNode, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, unusedValueExportToPlacateAjd as unused3} from './interfaces/node';
import {LQueries, QueryReadType, unusedValueExportToPlacateAjd as unused4} from './interfaces/query'; import {LQueries, QueryReadType, unusedValueExportToPlacateAjd as unused4} from './interfaces/query';
import {DIRECTIVES, LViewData, TVIEW} from './interfaces/view'; import {DIRECTIVES, LViewData, TVIEW} from './interfaces/view';
import {flatten, isContentQueryHost, readElementValue} from './util'; import {flatten, getLNode, isContentQueryHost} from './util';
const unusedValueToPlacateAjd = unused1 + unused2 + unused3 + unused4; const unusedValueToPlacateAjd = unused1 + unused2 + unused3 + unused4;
@ -121,7 +121,7 @@ export class LQueries_ implements LQueries {
insertView(index, this.deep); insertView(index, this.deep);
} }
addNode(tNode: TNode): LQueries|null { addNode(tNode: TElementNode|TContainerNode|TElementContainerNode): LQueries|null {
add(this.deep, tNode); add(this.deep, tNode);
if (isContentQueryHost(tNode)) { if (isContentQueryHost(tNode)) {
@ -278,13 +278,13 @@ function readFromNodeInjector(
return null; return null;
} }
function add(query: LQuery<any>| null, tNode: TNode) { function add(
query: LQuery<any>| null, tNode: TElementNode | TContainerNode | TElementContainerNode) {
const currentView = _getViewData(); const currentView = _getViewData();
// TODO: remove this lookup when nodeInjector is removed from LNode // TODO: remove this lookup when nodeInjector is removed from LNode
const currentNode = readElementValue(currentView[tNode.index]);
const nodeInjector = const nodeInjector =
getOrCreateNodeInjectorForNode(currentNode as LElementNode | LContainerNode, tNode); getOrCreateNodeInjectorForNode(getLNode(tNode, currentView), tNode, currentView);
while (query) { while (query) {
const predicate = query.predicate; const predicate = query.predicate;

View File

@ -8,7 +8,7 @@
import {devModeEqual} from '../change_detection/change_detection_util'; import {devModeEqual} from '../change_detection/change_detection_util';
import {assertLessThan} from './assert'; import {assertLessThan} from './assert';
import {LElementNode, TNode, TNodeFlags} from './interfaces/node'; import {LContainerNode, LElementContainerNode, LElementNode, TNode, TNodeFlags} from './interfaces/node';
import {HEADER_OFFSET, LViewData, TData} from './interfaces/view'; import {HEADER_OFFSET, LViewData, TData} from './interfaces/view';
/** /**
@ -91,6 +91,11 @@ export function readElementValue(value: LElementNode | any[]): LElementNode {
return (Array.isArray(value) ? (value as any as any[])[0] : value) as LElementNode; return (Array.isArray(value) ? (value as any as any[])[0] : value) as LElementNode;
} }
export function getLNode(tNode: TNode, hostView: LViewData): LElementNode|LContainerNode|
LElementContainerNode {
return readElementValue(hostView[tNode.index]);
}
export function isContentQueryHost(tNode: TNode): boolean { export function isContentQueryHost(tNode: TNode): boolean {
return (tNode.flags & TNodeFlags.hasContentQuery) !== 0; return (tNode.flags & TNodeFlags.hasContentQuery) !== 0;
} }

View File

@ -98,6 +98,9 @@
{ {
"name": "_CLEAN_PROMISE" "name": "_CLEAN_PROMISE"
}, },
{
"name": "_getViewData"
},
{ {
"name": "_renderCompCount" "name": "_renderCompCount"
}, },
@ -224,6 +227,9 @@
{ {
"name": "getHostElementNode" "name": "getHostElementNode"
}, },
{
"name": "getLNode"
},
{ {
"name": "getLViewChild" "name": "getLViewChild"
}, },

View File

@ -608,6 +608,9 @@
{ {
"name": "getLElementFromComponent" "name": "getLElementFromComponent"
}, },
{
"name": "getLNode"
},
{ {
"name": "getLViewChild" "name": "getLViewChild"
}, },

View File

@ -1088,9 +1088,6 @@
{ {
"name": "_enable_super_gross_mode_that_will_cause_bad_things" "name": "_enable_super_gross_mode_that_will_cause_bad_things"
}, },
{
"name": "_getComponentHostLElementNode"
},
{ {
"name": "_getViewData" "name": "_getViewData"
}, },
@ -1637,6 +1634,9 @@
{ {
"name": "getLElementFromComponent" "name": "getLElementFromComponent"
}, },
{
"name": "getLNode"
},
{ {
"name": "getLViewChild" "name": "getLViewChild"
}, },