Skip to content

Commit aedebaf

Browse files
karabenlesh
authored andcommitted
refactor(ivy): remove LNode.tNode (angular#25958)
PR Close angular#25958
1 parent 47f4412 commit aedebaf

21 files changed

Lines changed: 750 additions & 634 deletions

packages/core/src/render3/component.ts

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {CLEAN_PROMISE, _getComponentHostLElementNode, baseDirectiveCreate, creat
1818
import {ComponentDef, ComponentDefInternal, ComponentType} from './interfaces/definition';
1919
import {LElementNode} from './interfaces/node';
2020
import {RElement, RendererFactory3, domRendererFactory3} from './interfaces/renderer';
21-
import {LViewData, LViewFlags, RootContext, BINDING_INDEX, INJECTOR, CONTEXT, TVIEW} from './interfaces/view';
21+
import {LViewData, LViewFlags, RootContext, INJECTOR, CONTEXT, TVIEW} from './interfaces/view';
2222
import {stringify} from './util';
2323
import {getComponentDef} from './definition';
2424

@@ -53,7 +53,7 @@ export interface CreateComponentOptions {
5353
* features list because there's no way of knowing when the component will be used as
5454
* a root component.
5555
*/
56-
hostFeatures?: (<T>(component: T, componentDef: ComponentDef<T, string>) => void)[];
56+
hostFeatures?: HostFeature[];
5757

5858
/**
5959
* A function which is used to schedule change detection work in the future.
@@ -69,6 +69,9 @@ export interface CreateComponentOptions {
6969
scheduler?: (work: () => void) => void;
7070
}
7171

72+
/** See CreateComponentOptions.hostFeatures */
73+
type HostFeature = (<T>(component: T, componentDef: ComponentDef<T, string>) => void);
74+
7275
// TODO: A hack to not pull in the NullInjector from @angular/core.
7376
export const NULL_INJECTOR: Injector = {
7477
get: (token: any, notFoundValue?: any) => {
@@ -103,12 +106,13 @@ export function renderComponent<T>(
103106
// The first index of the first selector is the tag name.
104107
const componentTag = componentDef.selectors ![0] ![0] as string;
105108
const hostNode = locateHostElement(rendererFactory, opts.host || componentTag);
109+
const rootFlags = componentDef.onPush ? LViewFlags.Dirty | LViewFlags.IsRoot :
110+
LViewFlags.CheckAlways | LViewFlags.IsRoot;
106111
const rootContext = createRootContext(opts.scheduler || requestAnimationFrame.bind(window));
107112

108113
const rootView: LViewData = createLViewData(
109114
rendererFactory.createRenderer(hostNode, componentDef),
110-
createTView(-1, null, 1, 0, null, null, null), rootContext,
111-
componentDef.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways);
115+
createTView(-1, null, 1, 0, null, null, null), rootContext, rootFlags);
112116
rootView[INJECTOR] = opts.injector || null;
113117

114118
const oldView = enterView(rootView, null);
@@ -119,20 +123,10 @@ export function renderComponent<T>(
119123

120124
// Create element node at index 0 in data array
121125
elementNode = hostElement(componentTag, hostNode, componentDef, sanitizer);
122-
123-
// Create directive instance with factory() and store at index 0 in directives array
124-
component = baseDirectiveCreate(0, componentDef.factory() as T, componentDef, elementNode);
125-
if (componentDef.hostBindings) {
126-
queueHostBindingForCheck(0, componentDef.hostVars);
127-
}
128-
rootContext.components.push(component);
129-
(elementNode.data as LViewData)[CONTEXT] = component;
130-
initChangeDetectorIfExisting(elementNode.nodeInjector, component, elementNode.data !);
131-
132-
opts.hostFeatures && opts.hostFeatures.forEach((feature) => feature(component, componentDef));
126+
component = createRootComponent(
127+
elementNode, componentDef, rootView, rootContext, opts.hostFeatures || null);
133128

134129
executeInitAndContentHooks();
135-
setHostBindings(rootView[TVIEW].hostBindings);
136130
detectChangesInternal(elementNode.data as LViewData, component);
137131
} finally {
138132
leaveView(oldView);
@@ -142,6 +136,27 @@ export function renderComponent<T>(
142136
return component;
143137
}
144138

139+
/**
140+
* Creates a root component and sets it up with features and host bindings. Shared by
141+
* renderComponent() and ViewContainerRef.createComponent().
142+
*/
143+
export function createRootComponent<T>(
144+
elementNode: LElementNode, componentDef: ComponentDef<T, string>, rootView: LViewData,
145+
rootContext: RootContext, hostFeatures: HostFeature[] | null): any {
146+
// Create directive instance with factory() and store at index 0 in directives array
147+
const component = baseDirectiveCreate(0, componentDef.factory() as T, componentDef, elementNode);
148+
149+
if (componentDef.hostBindings) queueHostBindingForCheck(0, componentDef.hostVars);
150+
rootContext.components.push(component);
151+
(elementNode.data as LViewData)[CONTEXT] = component;
152+
initChangeDetectorIfExisting(elementNode.nodeInjector, component, elementNode.data as LViewData);
153+
154+
hostFeatures && hostFeatures.forEach((feature) => feature(component, componentDef));
155+
setHostBindings(rootView[TVIEW].hostBindings);
156+
return component;
157+
}
158+
159+
145160
export function createRootContext(scheduler: (workFn: () => void) => void): RootContext {
146161
return {
147162
components: [],
@@ -169,7 +184,8 @@ export function LifecycleHooksFeature(component: any, def: ComponentDefInternal<
169184
// Root component is always created at dir index 0
170185
const tView = elementNode.view[TVIEW];
171186
queueInitHooks(0, def.onInit, def.doCheck, tView);
172-
queueLifecycleHooks(elementNode.tNode.flags, tView);
187+
// Directive starting index 0, directive count 1 -> directive flags: 1
188+
queueLifecycleHooks(1, tView);
173189
}
174190

175191
/**

packages/core/src/render3/component_ref.ts

Lines changed: 20 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ import {RendererFactory2} from '../render/api';
1717
import {Type} from '../type';
1818

1919
import {assertComponentType, assertDefined} from './assert';
20-
import {LifecycleHooksFeature, createRootContext} from './component';
20+
import {LifecycleHooksFeature, createRootComponent, createRootContext} from './component';
2121
import {getComponentDef} from './definition';
22-
import {adjustBlueprintForNewNode, baseDirectiveCreate, createLNode, createLViewData, createTView, elementCreate, enterView, hostElement, initChangeDetectorIfExisting, locateHostElement, queueHostBindingForCheck, renderEmbeddedTemplate, setHostBindings} from './instructions';
23-
import {ComponentDefInternal, ComponentType, RenderFlags} from './interfaces/definition';
24-
import {LElementNode, TNode, TNodeType} from './interfaces/node';
22+
import {adjustBlueprintForNewNode, createLViewData, createNodeAtIndex, createTView, elementCreate, enterView, getTNode, hostElement, locateHostElement, renderEmbeddedTemplate} from './instructions';
23+
import {ComponentDefInternal, RenderFlags} from './interfaces/definition';
24+
import {LElementNode, TElementNode, TNode, TNodeType, TViewNode} from './interfaces/node';
2525
import {RElement, RendererFactory3, domRendererFactory3} from './interfaces/renderer';
26-
import {CONTEXT, FLAGS, INJECTOR, LViewData, LViewFlags, RootContext, TVIEW} from './interfaces/view';
26+
import {FLAGS, INJECTOR, LViewData, LViewFlags, RootContext, TVIEW} from './interfaces/view';
2727
import {RootViewRef, ViewRef} from './view_ref';
2828

2929
export class ComponentFactoryResolver extends viewEngine_ComponentFactoryResolver {
@@ -115,70 +115,60 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
115115
// The first index of the first selector is the tag name.
116116
const componentTag = this.componentDef.selectors ![0] ![0] as string;
117117

118+
const rootFlags = this.componentDef.onPush ? LViewFlags.Dirty | LViewFlags.IsRoot :
119+
LViewFlags.CheckAlways | LViewFlags.IsRoot;
118120
const rootContext: RootContext = ngModule && !isInternalRootView ?
119121
ngModule.injector.get(ROOT_CONTEXT) :
120122
createRootContext(requestAnimationFrame.bind(window));
121123

122124
// Create the root view. Uses empty TView and ContentTemplate.
123125
const rootView: LViewData = createLViewData(
124126
rendererFactory.createRenderer(hostNode, this.componentDef),
125-
createTView(-1, null, 1, 0, null, null, null), rootContext,
126-
this.componentDef.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways);
127+
createTView(-1, null, 1, 0, null, null, null), rootContext, rootFlags);
127128
rootView[INJECTOR] = ngModule && ngModule.injector || null;
128129

129130
// rootView is the parent when bootstrapping
130131
const oldView = enterView(rootView, null);
131132

132133
let component: T;
133134
let elementNode: LElementNode;
135+
let tElementNode: TElementNode;
134136
try {
135137
if (rendererFactory.begin) rendererFactory.begin();
136138

137139
// Create element node at index 0 in data array
138140
elementNode = hostElement(componentTag, hostNode, this.componentDef);
139-
const componentView = elementNode.data as LViewData;
140141

141-
// Create directive instance with factory() and store at index 0 in directives array
142-
component =
143-
baseDirectiveCreate(0, this.componentDef.factory(), this.componentDef, elementNode);
144-
if (this.componentDef.hostBindings) {
145-
queueHostBindingForCheck(0, this.componentDef.hostVars);
146-
}
147-
rootContext.components.push(component);
148-
initChangeDetectorIfExisting(elementNode.nodeInjector, component, componentView);
149-
componentView[CONTEXT] = component;
150142
// TODO: should LifecycleHooksFeature and other host features be generated by the compiler and
151143
// executed here?
152144
// Angular 5 reference: https://stackblitz.com/edit/lifecycle-hooks-vcref
153-
LifecycleHooksFeature(component, this.componentDef);
145+
component = createRootComponent(
146+
elementNode, this.componentDef, rootView, rootContext, [LifecycleHooksFeature]);
154147

155-
setHostBindings(rootView[TVIEW].hostBindings);
148+
tElementNode = getTNode(0) as TElementNode;
156149

157150
// Transform the arrays of native nodes into a LNode structure that can be consumed by the
158151
// projection instruction. This is needed to support the reprojection of these nodes.
159152
if (projectableNodes) {
160153
let index = 0;
161-
const projection: TNode[] = elementNode.tNode.projection = [];
154+
const projection: TNode[] = tElementNode.projection = [];
162155
for (let i = 0; i < projectableNodes.length; i++) {
163156
const nodeList = projectableNodes[i];
164157
let firstTNode: TNode|null = null;
165158
let previousTNode: TNode|null = null;
166159
for (let j = 0; j < nodeList.length; j++) {
167160
adjustBlueprintForNewNode(rootView);
168-
const lNode =
169-
createLNode(++index, TNodeType.Element, nodeList[j] as RElement, null, null);
170-
if (previousTNode) {
171-
previousTNode.next = lNode.tNode;
172-
} else {
173-
firstTNode = lNode.tNode;
174-
}
175-
previousTNode = lNode.tNode;
161+
const tNode =
162+
createNodeAtIndex(++index, TNodeType.Element, nodeList[j] as RElement, null, null);
163+
previousTNode ? (previousTNode.next = tNode) : (firstTNode = tNode);
164+
previousTNode = tNode;
176165
}
177166
projection.push(firstTNode !);
178167
}
179168
}
180169

181170
// Execute the template in creation mode only, and then turn off the CreationMode flag
171+
const componentView = elementNode.data as LViewData;
182172
renderEmbeddedTemplate(componentView, componentView[TVIEW], component, RenderFlags.Create);
183173
componentView[FLAGS] &= ~LViewFlags.CreationMode;
184174
} finally {
@@ -190,7 +180,7 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
190180
new ComponentRef(this.componentType, component, rootView, injector, hostNode !);
191181
if (isInternalRootView) {
192182
// The host element of the internal root view is attached to the component's host view node
193-
componentRef.hostView._lViewNode !.tNode.child = elementNode.tNode;
183+
componentRef.hostView._tViewNode !.child = tElementNode;
194184
}
195185
return componentRef;
196186
}
@@ -219,7 +209,7 @@ export class ComponentRef<T> extends viewEngine_ComponentRef<T> {
219209
super();
220210
this.instance = instance;
221211
this.hostView = this.changeDetectorRef = new RootViewRef<T>(rootView);
222-
this.hostView._lViewNode = createLNode(-1, TNodeType.View, null, null, null, rootView);
212+
this.hostView._tViewNode = createNodeAtIndex(-1, TNodeType.View, null, null, null, rootView);
223213
this.injector = injector;
224214
this.location = new viewEngine_ElementRef(hostNode);
225215
this.componentType = componentType;

packages/core/src/render3/context_discovery.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -321,9 +321,8 @@ function findViaDirective(lViewData: LViewData, directiveInstance: {}): number {
321321
if (directiveIndex >= 0) {
322322
let tNode = lViewData[TVIEW].firstChild;
323323
while (tNode) {
324-
const lNode = getLNodeFromViewData(lViewData, tNode.index) !;
325-
const directiveIndexStart = getDirectiveStartIndex(lNode);
326-
const directiveIndexEnd = getDirectiveEndIndex(lNode, directiveIndexStart);
324+
const directiveIndexStart = getDirectiveStartIndex(tNode);
325+
const directiveIndexEnd = getDirectiveEndIndex(tNode, directiveIndexStart);
327326
if (directiveIndex >= directiveIndexStart && directiveIndex < directiveIndexEnd) {
328327
return tNode.index;
329328
}
@@ -357,10 +356,11 @@ function getLNodeFromViewData(lViewData: LViewData, lElementIndex: number): LEle
357356
function discoverDirectiveIndices(lViewData: LViewData, lNodeIndex: number): number[]|null {
358357
const directivesAcrossView = lViewData[DIRECTIVES];
359358
const lNode = getLNodeFromViewData(lViewData, lNodeIndex);
359+
const tNode = lViewData[TVIEW].data[lNodeIndex] as TNode;
360360
if (lNode && directivesAcrossView && directivesAcrossView.length) {
361361
// this check for tNode is to determine if the calue is a LEmementNode instance
362-
const directiveIndexStart = getDirectiveStartIndex(lNode);
363-
const directiveIndexEnd = getDirectiveEndIndex(lNode, directiveIndexStart);
362+
const directiveIndexStart = getDirectiveStartIndex(tNode);
363+
const directiveIndexEnd = getDirectiveEndIndex(tNode, directiveIndexStart);
364364
const directiveIndices: number[] = [];
365365
for (let i = directiveIndexStart; i < directiveIndexEnd; i++) {
366366
// special case since the instance of the component (if it exists)
@@ -388,17 +388,17 @@ function discoverDirectives(lViewData: LViewData, directiveIndices: number[]): n
388388
return directives;
389389
}
390390

391-
function getDirectiveStartIndex(lNode: LElementNode): number {
391+
function getDirectiveStartIndex(tNode: TNode): number {
392392
// the tNode instances store a flag value which then has a
393393
// pointer which tells the starting index of where all the
394394
// active directives are in the master directive array
395-
return lNode.tNode.flags >> TNodeFlags.DirectiveStartingIndexShift;
395+
return tNode.flags >> TNodeFlags.DirectiveStartingIndexShift;
396396
}
397397

398-
function getDirectiveEndIndex(lNode: LElementNode, startIndex: number): number {
399-
// The end value is also apart of the same flag
398+
function getDirectiveEndIndex(tNode: TNode, startIndex: number): number {
399+
// The end value is also a part of the same flag
400400
// (see `TNodeFlags` to see how the flag bit shifting
401401
// values are used).
402-
const count = lNode.tNode.flags & TNodeFlags.DirectiveCountMask;
402+
const count = tNode.flags & TNodeFlags.DirectiveCountMask;
403403
return count ? (startIndex + count) : -1;
404404
}

0 commit comments

Comments
 (0)