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 {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 {LElementNode} from './interfaces/node';
import {RElement, RendererFactory3, domRendererFactory3} from './interfaces/renderer';
import {LViewData, LViewFlags, RootContext, INJECTOR, CONTEXT, TVIEW} from './interfaces/view';
import {stringify} from './util';
import {getComponentDef} from './definition';
import {getLElementFromComponent, readPatchedLViewData} from './context_discovery';
/** 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 {
const elementNode = _getComponentHostLElementNode(component);
const rootTView = readPatchedLViewData(component) ![TVIEW];
// Root component is always created at dir index 0
const tView = elementNode.view[TVIEW];
queueInitHooks(0, def.onInit, def.doCheck, tView);
queueInitHooks(0, def.onInit, def.doCheck, rootTView);
// 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.
*/
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
* 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 lNode: LElementNode;
@ -355,10 +355,9 @@ function getLNodeFromViewData(lViewData: LViewData, lElementIndex: number): LEle
*/
function discoverDirectiveIndices(lViewData: LViewData, lNodeIndex: number): number[]|null {
const directivesAcrossView = lViewData[DIRECTIVES];
const lNode = getLNodeFromViewData(lViewData, lNodeIndex);
const tNode = lViewData[TVIEW].data[lNodeIndex] as TNode;
if (lNode && directivesAcrossView && directivesAcrossView.length) {
// this check for tNode is to determine if the calue is a LEmementNode instance
if (directivesAcrossView && directivesAcrossView.length) {
// this check for tNode is to determine if the value is a LElementNode instance
const directiveIndexStart = getDirectiveStartIndex(tNode);
const directiveIndexEnd = getDirectiveEndIndex(tNode, directiveIndexStart);
const directiveIndices: number[] = [];

View File

@ -26,17 +26,17 @@ import {Type} from '../type';
import {assertDefined, assertGreaterThan, assertLessThan} from './assert';
import {ComponentFactoryResolver} from './component_ref';
import {getComponentDef, getDirectiveDef, getPipeDef} from './definition';
import {_getViewData, addToViewTree, assertPreviousIsParent, createEmbeddedViewAndNode, createLContainer, createLNodeObject, createTNode, getPreviousOrParentNode, getPreviousOrParentTNode, getRenderer, renderEmbeddedTemplate, resolveDirective} from './instructions';
import {RENDER_PARENT, VIEWS} from './interfaces/container';
import {_getViewData, addToViewTree, assertPreviousIsParent, createEmbeddedViewAndNode, createLContainer, createLNodeObject, createTNode, getPreviousOrParentNode, getPreviousOrParentTNode, getRenderer, loadElement, renderEmbeddedTemplate, resolveDirective} from './instructions';
import {LContainer, RENDER_PARENT, VIEWS} from './interfaces/container';
import {DirectiveDefInternal, RenderFlags} from './interfaces/definition';
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 {RElement, Renderer3, isProceduralRenderer} from './interfaces/renderer';
import {CONTEXT, DIRECTIVES, HOST_NODE, INJECTOR, LViewData, PARENT, QUERIES, RENDERER, TVIEW, TView} from './interfaces/view';
import {Renderer3, isProceduralRenderer} from './interfaces/renderer';
import {CONTEXT, DIRECTIVES, HOST_NODE, INJECTOR, LViewData, QUERIES, RENDERER, TVIEW, TView} from './interfaces/view';
import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert';
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';
@ -103,28 +103,32 @@ export function getOrCreateNodeInjector(): LInjector {
ngDevMode && assertPreviousIsParent();
return getOrCreateNodeInjectorForNode(
getPreviousOrParentNode() as LElementNode | LElementContainerNode | LContainerNode,
getPreviousOrParentTNode());
getPreviousOrParentTNode() as TElementNode | TElementContainerNode | TContainerNode,
_getViewData());
}
/**
* Creates (or gets an existing) injector for a given element or container.
*
* @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
*/
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
const nodeInjector = node.nodeInjector;
const parentLNode = getParentOrContainerNode(tNode, node.view);
const parentLNode = getParentOrContainerNode(tNode, hostView);
const parentInjector = parentLNode && parentLNode.nodeInjector;
if (nodeInjector != parentInjector) {
return nodeInjector !;
}
return node.nodeInjector = {
parent: parentInjector,
node: node,
tNode: tNode,
view: hostView,
bf0: 0,
bf1: 0,
bf2: 0,
@ -306,11 +310,12 @@ export function getOrCreateChangeDetectorRef(
di: LInjector, context: any): viewEngine_ChangeDetectorRef {
if (di.changeDetectorRef) return di.changeDetectorRef;
const currentTNode = getPreviousOrParentTNode();
const currentTNode = di.tNode;
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) {
return di.changeDetectorRef = getOrCreateHostChangeDetector(_getViewData());
return di.changeDetectorRef = getOrCreateHostChangeDetector(di.view);
}
return null !;
}
@ -326,7 +331,7 @@ function getOrCreateHostChangeDetector(currentView: LViewData): viewEngine_Chang
}
function getOrCreateRenderer2(di: LInjector): Renderer2 {
const renderer = di.node.view[RENDERER];
const renderer = di.view[RENDERER];
if (isProceduralRenderer(renderer)) {
return renderer as Renderer2;
} 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
// directives associated with the injector's corresponding node to get the directive instance.
const node = injector.node;
const tNode = injector.tNode;
const injectorView = injector.view;
const nodeFlags = tNode.flags;
const count = nodeFlags & TNodeFlags.DirectiveCountMask;
if (count !== 0) {
const start = nodeFlags >> TNodeFlags.DirectiveStartingIndexShift;
const end = start + count;
const defs = node.view[TVIEW].directives !;
const defs = injectorView[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 DirectiveDefInternal<any>;
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.
let instance: T|null;
if (injector === nodeInjector &&
(instance = searchMatchesQueuedForCreation<T>(node, token))) {
(instance = searchMatchesQueuedForCreation<T>(token, injectorView[TVIEW]))) {
return instance;
}
@ -406,7 +411,7 @@ export function getOrCreateInjectable<T>(
}
}
const moduleInjector = getPreviousOrParentNode() !.view[INJECTOR];
const moduleInjector = nodeInjector.view[INJECTOR];
const formerInjector = setCurrentInjector(moduleInjector);
try {
return inject(token, flags);
@ -415,13 +420,13 @@ export function getOrCreateInjectable<T>(
}
}
function searchMatchesQueuedForCreation<T>(node: LNode, token: any): T|null {
const matches = node.view[TVIEW].currentMatches;
function searchMatchesQueuedForCreation<T>(token: any, hostTView: TView): T|null {
const matches = hostTView.currentMatches;
if (matches) {
for (let i = 0; i < matches.length; i += 2) {
const def = matches[i] as DirectiveDefInternal<any>;
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.
*/
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> {
@ -543,7 +548,7 @@ export class ReadFromInjectorFn<T> {
* @returns The ElementRef instance to use
*/
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>>>(
@ -563,7 +568,7 @@ export const QUERY_READ_FROM_NODE =
ngDevMode && assertNodeOfPossibleTypes(
tNode, TNodeType.Container, TNodeType.Element, TNodeType.ElementContainer);
if (directiveIdx > -1) {
return _getViewData()[DIRECTIVES] ![directiveIdx];
return injector.view[DIRECTIVES] ![directiveIdx];
}
if (tNode.type === TNodeType.Element || tNode.type === TNodeType.ElementContainer) {
return getOrCreateElementRef(injector);
@ -594,11 +599,11 @@ export function getOrCreateContainerRef(di: LInjector): viewEngine_ViewContainer
ngDevMode && assertNodeOfPossibleTypes(
hostTNode, TNodeType.Container, TNodeType.Element, TNodeType.ElementContainer);
const hostView = hostLNode.view;
const hostView = di.view;
const lContainer = createLContainer(hostView, true);
const comment = hostView[RENDERER].createComment(ngDevMode ? 'container' : '');
const lContainerNode: LContainerNode = createLNodeObject(
TNodeType.Container, hostView, hostLNode.nodeInjector, comment, lContainer);
const lContainerNode: LContainerNode =
createLNodeObject(TNodeType.Container, hostLNode.nodeInjector, comment, lContainer);
lContainer[RENDER_PARENT] = getRenderParent(hostTNode, hostView);
@ -613,7 +618,7 @@ export function getOrCreateContainerRef(di: LInjector): viewEngine_ViewContainer
addToViewTree(hostView, hostTNode.index as number, lContainer);
di.viewContainerRef = new ViewContainerRef(
lContainerNode, hostTNode.dynamicContainerNode as TContainerNode, hostLNode, hostTNode);
lContainer, hostTNode.dynamicContainerNode as TContainerNode, hostTNode, hostView);
}
return di.viewContainerRef;
@ -651,49 +656,49 @@ class ViewContainerRef extends viewEngine_ViewContainerRef {
private _viewRefs: viewEngine_ViewRef[] = [];
constructor(
private _lContainerNode: LContainerNode, private _tContainerNode: TContainerNode,
private _hostNode: LElementNode|LElementContainerNode|LContainerNode,
private _hostTNode: TNode) {
private _lContainer: LContainer, private _tContainerNode: TContainerNode,
private _hostTNode: TElementNode|TContainerNode|TElementContainerNode,
private _hostView: LViewData) {
super();
}
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);
}
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);
}
/** @deprecated No replacement */
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();
}
clear(): void {
const lContainer = this._lContainerNode.data;
while (lContainer[VIEWS].length) {
while (this._lContainer[VIEWS].length) {
this.remove(0);
}
}
get(index: number): viewEngine_ViewRef|null { return this._viewRefs[index] || null; }
get length(): number {
const lContainer = this._lContainerNode.data;
return lContainer[VIEWS].length;
}
get length(): number { return this._lContainer[VIEWS].length; }
createEmbeddedView<C>(templateRef: viewEngine_TemplateRef<C>, context?: C, index?: number):
viewEngine_EmbeddedViewRef<C> {
const adjustedIdx = this._adjustIndex(index);
const viewRef =
(templateRef as TemplateRef<C>)
.createEmbeddedView(
context || <any>{}, this._lContainerNode, this._tContainerNode, adjustedIdx);
const viewRef = (templateRef as TemplateRef<C>)
.createEmbeddedView(
context || <any>{}, this._lContainer, this._tContainerNode,
this._hostView, adjustedIdx);
(viewRef as ViewRef<any>).attachToViewContainerRef(this);
this._viewRefs.splice(adjustedIdx, 0, viewRef);
return viewRef;
@ -721,9 +726,11 @@ class ViewContainerRef extends viewEngine_ViewContainerRef {
const lView = (viewRef as ViewRef<any>)._view !;
const adjustedIdx = this._adjustIndex(index);
insertView(this._lContainerNode, lView, adjustedIdx, this._tContainerNode.parent !.index);
const beforeNode =
getBeforeNodeForView(adjustedIdx, this._lContainerNode.data[VIEWS], this._lContainerNode);
insertView(
lView, this._lContainer, this._hostView, adjustedIdx, this._tContainerNode.parent !.index);
const container = this._getHostNode().dynamicLContainerNode !;
const beforeNode = getBeforeNodeForView(adjustedIdx, this._lContainer[VIEWS], container);
addRemoveViewFromContainer(lView, true, beforeNode);
(viewRef as ViewRef<any>).attachToViewContainerRef(this);
@ -743,27 +750,29 @@ class ViewContainerRef extends viewEngine_ViewContainerRef {
remove(index?: number): void {
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);
}
detach(index?: number): viewEngine_ViewRef|null {
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;
}
private _adjustIndex(index?: number, shift: number = 0) {
if (index == null) {
return this._lContainerNode.data[VIEWS].length + shift;
return this._lContainer[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._lContainer[VIEWS].length + 1 + shift, '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 && assertDefined(hostTNode.tViews, 'TView must be allocated');
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]);
}
return di.templateRef;
@ -818,12 +827,12 @@ class TemplateRef<T> extends viewEngine_TemplateRef<T> {
}
createEmbeddedView(
context: T, containerNode?: LContainerNode, tContainerNode?: TContainerNode,
context: T, container?: LContainer, tContainerNode?: TContainerNode, hostView?: LViewData,
index?: number): viewEngine_EmbeddedViewRef<T> {
const lView = createEmbeddedViewAndNode(
this._tView, context, this._declarationParentView, this._renderer, this._queries);
if (containerNode) {
insertView(containerNode, lView, index !, tContainerNode !.parent !.index);
if (container) {
insertView(lView, container, hostView !, index !, tContainerNode !.parent !.index);
}
renderEmbeddedTemplate(lView, this._tView, context, RenderFlags.Create);
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
* `<ng-template>` element.
*/
export function templateRefExtractor(lNode: LNodeWithLocalRefs, tNode: TNode) {
return getOrCreateTemplateRef(getOrCreateNodeInjectorForNode(lNode, tNode));
export function templateRefExtractor(tNode: TContainerNode, currentView: LViewData) {
// 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();
// 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 (previousTNode === parentTNode && tNode !== 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 {ComponentDefInternal, ComponentQuery, ComponentTemplate, DirectiveDefInternal, DirectiveDefListOrFactory, InitialStylingFlags, PipeDefListOrFactory, RenderFlags} from './interfaces/definition';
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 {LQueries} from './interfaces/query';
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 {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 {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';
@ -132,7 +132,7 @@ let previousOrParentTNode: TNode;
export function getPreviousOrParentNode(): LNode|null {
return previousOrParentTNode == null || previousOrParentTNode === viewData[HOST_NODE] ?
getHostElementNode(viewData) :
readElementValue(viewData[previousOrParentTNode.index]);
getLNode(previousOrParentTNode, viewData);
}
export function getPreviousOrParentTNode(): TNode {
@ -393,12 +393,10 @@ export function createLViewData<T>(
* (same properties assigned in the same order).
*/
export function createLNodeObject(
type: TNodeType, currentView: LViewData, nodeInjector: LInjector | null,
native: RText | RElement | RComment | null,
type: TNodeType, nodeInjector: LInjector | null, native: RText | RElement | RComment | null,
state: any): LElementNode&LTextNode&LViewNode&LContainerNode&LProjectionNode {
return {
native: native as any,
view: currentView,
nodeInjector: nodeInjector,
data: state,
dynamicLContainerNode: null
@ -445,7 +443,7 @@ export function createNodeAtIndex(
const tParent = parentInSameView ? parent as TElementNode | TContainerNode : 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;
if (index === -1 || type === TNodeType.View) {
@ -780,7 +778,8 @@ export function elementContainerEnd(): void {
}
ngDevMode && assertNodeType(previousOrParentTNode, TNodeType.ElementContainer);
currentQueries && (currentQueries = currentQueries.addNode(previousOrParentTNode));
currentQueries &&
(currentQueries = currentQueries.addNode(previousOrParentTNode as TElementContainerNode));
queueLifecycleHooks(previousOrParentTNode.flags, tView);
}
@ -848,8 +847,8 @@ export function elementCreate(name: string, overriddenRenderer?: Renderer3): REl
return native;
}
function nativeNodeLocalRefExtractor(lNode: LNodeWithLocalRefs, tNode: TNode): RNode {
return lNode.native;
function nativeNodeLocalRefExtractor(tNode: TNode, currentView: LViewData): RNode {
return getLNode(tNode, currentView).native;
}
/**
@ -1018,13 +1017,12 @@ function saveNameToExportMap(
*/
function saveResolvedLocalsInData(localRefExtractor: LocalRefExtractor): void {
const localNames = previousOrParentTNode.localNames;
const node = getPreviousOrParentNode() as LElementNode;
const tNode = previousOrParentTNode as TElementNode | TContainerNode | TElementContainerNode;
if (localNames) {
let localIndex = previousOrParentTNode.index + 1;
for (let i = 0; i < localNames.length; i += 2) {
const index = localNames[i + 1] as number;
const value =
index === -1 ? localRefExtractor(node, previousOrParentTNode) : directives ![index];
const value = index === -1 ? localRefExtractor(tNode, viewData) : directives ![index];
viewData[localIndex++] = value;
}
}
@ -1206,7 +1204,6 @@ export function hostElement(
if (def.diPublic) def.diPublic(def);
tView.directives = [def];
}
return viewData[HEADER_OFFSET];
}
@ -1316,7 +1313,8 @@ export function elementEnd(): void {
previousOrParentTNode = previousOrParentTNode.parent !;
}
ngDevMode && assertNodeType(previousOrParentTNode, TNodeType.Element);
currentQueries && (currentQueries = currentQueries.addNode(previousOrParentTNode));
currentQueries &&
(currentQueries = currentQueries.addNode(previousOrParentTNode as TElementNode));
queueLifecycleHooks(previousOrParentTNode.flags, tView);
elementDepthCount--;
@ -1923,7 +1921,8 @@ export function template(
}
createDirectivesAndLocals(localRefs, localRefExtractor);
currentQueries && (currentQueries = currentQueries.addNode(previousOrParentTNode));
currentQueries &&
(currentQueries = currentQueries.addNode(previousOrParentTNode as TContainerNode));
queueLifecycleHooks(tNode.flags, tView);
isParent = false;
}
@ -2004,14 +2003,15 @@ export function containerRefreshEnd(): void {
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);
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
while (nextIndex < container.data[VIEWS].length) {
removeView(container, previousOrParentTNode as TContainerNode, nextIndex);
while (nextIndex < lContainer[VIEWS].length) {
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.
* 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 viewBlockId exact view block id to look for
* @returns index of a found view or -1 if not found
*/
function scanForView(
containerNode: LContainerNode, tContainerNode: TContainerNode, startIdx: number,
lContainer: LContainer, tContainerNode: TContainerNode, startIdx: number,
viewBlockId: number): LViewData|null {
const views = containerNode.data[VIEWS];
const views = lContainer[VIEWS];
for (let i = startIdx; i < views.length; i++) {
const viewAtPositionId = views[i][TVIEW].id;
if (viewAtPositionId === viewBlockId) {
return views[i];
} else if (viewAtPositionId < viewBlockId) {
// found a view that should not be at this position - remove
removeView(containerNode, tContainerNode, i);
removeView(lContainer, tContainerNode, i);
} else {
// 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
@ -2082,11 +2083,12 @@ export function embeddedViewStart(viewBlockId: number, consts: number, vars: num
previousOrParentTNode;
// Inline containers cannot have style bindings, so we can read the value directly
const container = viewData[containerTNode.index] as LContainerNode;
const currentView = viewData;
ngDevMode && assertNodeType(containerTNode, TNodeType.Container);
const lContainer = container.data;
let viewToRender = scanForView(
container, containerTNode as TContainerNode, lContainer[ACTIVE_INDEX] !, viewBlockId);
lContainer, containerTNode as TContainerNode, lContainer[ACTIVE_INDEX] !, viewBlockId);
if (viewToRender) {
isParent = true;
@ -2108,7 +2110,7 @@ export function embeddedViewStart(viewBlockId: number, consts: number, vars: num
if (container) {
if (creationMode) {
// 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] !++;
}
@ -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})`);
}
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;

View File

@ -6,12 +6,14 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ChangeDetectorRef} from '../../change_detection/change_detector_ref';
import {ElementRef} from '../../linker/element_ref';
import {TemplateRef} from '../../linker/template_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 {
/**
@ -20,15 +22,14 @@ export interface LInjector {
*/
readonly parent: LInjector|null;
/**
* Allows access to the directives array in that node's static data and to
* 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;
/** Necessary to find directive indices for a particular node and look up the LNode. */
readonly tNode: TElementNode|TElementContainerNode|TContainerNode;
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

View File

@ -81,13 +81,6 @@ export interface LNode {
*/
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. */
nodeInjector: LInjector|null;
@ -530,9 +523,9 @@ export type InitialInputs = string[];
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.
@ -540,4 +533,4 @@ export type LNodeWithLocalRefs = LContainerNode | LElementNode | LElementContain
* - `<div #nativeDivEl>` - `nativeDivEl` should point to the native `<div>` element;
* - `<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 {Type} from '../../type';
import {TNode} from './node';
import {TContainerNode, TElementContainerNode, TElementNode, TNode} from './node';
/** Used for tracking queries (e.g. ViewChild, ContentChild). */
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
* 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

View File

@ -10,12 +10,12 @@ import {assertDefined} from './assert';
import {attachPatchData} from './context_discovery';
import {callHooks} from './hooks';
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 {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 {assertNodeType} from './node_assert';
import {isComponent, readElementValue, stringify} from './util';
import {getLNode, readElementValue, stringify} from './util';
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|
LElementContainerNode|LContainerNode|null {
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 {
const hostTNode = currentView[HOST_NODE] as TElementNode;
return hostTNode && hostTNode.type !== TNodeType.View ?
readElementValue(currentView[PARENT] ![hostTNode.index]) :
(getLNode(hostTNode, currentView[PARENT] !) as LElementNode) :
null;
}
@ -117,7 +117,7 @@ function walkTNodeTree(
let nextTNode: TNode|null = null;
const parent = renderParentNode ? renderParentNode.native : null;
if (tNode.type === TNodeType.Element) {
const elementNode = readElementValue(currentView ![tNode.index]);
const elementNode = getLNode(tNode, currentView);
executeNodeAction(action, renderer, parent, elementNode.native !, beforeNode);
if (elementNode.dynamicLContainerNode) {
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
* the container's parent view is added later).
*
* @param container The container into which the view should be inserted
* @param viewNode The view to insert
* @param lView 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
* @returns The inserted view
* @param containerIndex The index of the container node, if dynamic
*/
export function insertView(
container: LContainerNode, lView: LViewData, index: number, containerIndex: number) {
const state = container.data;
const views = state[VIEWS];
lView: LViewData, lContainer: LContainer, parentView: LViewData, index: number,
containerIndex: number) {
const views = lContainer[VIEWS];
if (index > 0) {
// 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.
if (containerIndex > -1) {
lView[CONTAINER_INDEX] = containerIndex;
lView[PARENT] = container.view;
lView[PARENT] = parentView;
}
// 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
* 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
* @returns The detached view
* @param detached Whether or not this view is already detached.
*/
export function detachView(container: LContainerNode, removeIndex: number, detached: boolean) {
const views = container.data[VIEWS];
export function detachView(lContainer: LContainer, removeIndex: number, detached: boolean) {
const views = lContainer[VIEWS];
const viewToDetach = views[removeIndex];
if (removeIndex > 0) {
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.
*
* @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
* @returns The removed view
*/
export function removeView(
container: LContainerNode, tContainer: TContainerNode, removeIndex: number) {
const view = container.data[VIEWS][removeIndex];
lContainer: LContainer, tContainer: TContainerNode, removeIndex: number) {
const view = lContainer[VIEWS][removeIndex];
destroyLView(view);
detachView(container, removeIndex, !!tContainer.detached);
detachView(lContainer, removeIndex, !!tContainer.detached);
}
/** Gets the child of the given LViewData */
@ -680,8 +681,7 @@ export function getBeforeNodeForView(index: number, views: LViewData[], containe
if (index + 1 < views.length) {
const view = views[index + 1] as LViewData;
const viewTNode = view[HOST_NODE] as TViewNode;
return viewTNode.child ? readElementValue(view[viewTNode.child.index]).native :
container.native;
return viewTNode.child ? getLNode(viewTNode.child, view).native : container.native;
} else {
return container.native;
}
@ -745,7 +745,7 @@ export function appendProjectedNode(
} else if (projectedTNode.type === TNodeType.ElementContainer) {
let ngContainerChildTNode: TNode|null = projectedTNode.child as TNode;
while (ngContainerChildTNode) {
let ngContainerChild = readElementValue(projectionView[ngContainerChildTNode.index]);
let ngContainerChild = getLNode(ngContainerChildTNode, projectionView);
appendProjectedNode(
ngContainerChild as LElementNode | LElementContainerNode | LTextNode | LContainerNode,
ngContainerChildTNode, tProjectionNode, currentView, projectionView);

View File

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

View File

@ -8,7 +8,7 @@
import {devModeEqual} from '../change_detection/change_detection_util';
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';
/**
@ -91,6 +91,11 @@ export function readElementValue(value: LElementNode | any[]): 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 {
return (tNode.flags & TNodeFlags.hasContentQuery) !== 0;
}

View File

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

View File

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

View File

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