refactor(compiler): don’t use `AppElement`s for creating component views

This commit is contained in:
Tobias Bosch 2016-11-01 09:35:03 -07:00 committed by vikerman
parent 13533d2a30
commit d1035da85c
11 changed files with 79 additions and 66 deletions

View File

@ -73,7 +73,7 @@ export class CompileElement extends CompileNode {
this.instances.set(resolveIdentifierToken(Identifiers.Injector).reference, this.injector);
this.instances.set(
resolveIdentifierToken(Identifiers.Renderer).reference, o.THIS_EXPR.prop('renderer'));
if (this.hasViewContainer || this.hasEmbeddedView || isPresent(this.component)) {
if (this.hasViewContainer || this.hasEmbeddedView) {
this._createAppElement();
}
if (this.component) {

View File

@ -40,7 +40,9 @@ export class ChangeDetectorStatusEnum {
export class ViewConstructorVars {
static viewUtils = o.variable('viewUtils');
static parentInjector = o.variable('parentInjector');
static declarationEl = o.variable('declarationEl');
static parentView = o.variable('parentView');
static parentIndex = o.variable('parentIndex');
static parentElement = o.variable('parentElement');
}
export class ViewProperties {

View File

@ -24,7 +24,7 @@ export function getPropertyInView(
var currView: CompileView = callingView;
while (currView !== definedView && isPresent(currView.declarationElement.view)) {
currView = currView.declarationElement.view;
viewProp = viewProp.prop('parent');
viewProp = viewProp.prop('parentView');
}
if (currView !== definedView) {
throw new Error(

View File

@ -233,12 +233,12 @@ class ViewBuilderVisitor implements TemplateAstVisitor {
o.importType(resolveIdentifier(Identifiers.AppView), [o.importType(component.type)])));
this.view.viewChildren.push(compViewExpr);
compileElement.setComponentView(compViewExpr);
this.view.createMethod.addStmt(
compViewExpr
.set(o.importExpr(nestedComponentIdentifier).callFn([
ViewProperties.viewUtils, compileElement.injector, compileElement.appElement
]))
.toStmt());
this.view.createMethod.addStmt(compViewExpr
.set(o.importExpr(nestedComponentIdentifier).callFn([
ViewProperties.viewUtils, compileElement.injector,
o.THIS_EXPR, o.literal(nodeIndex), renderNode
]))
.toStmt());
}
compileElement.beforeChildren();
this._addRootNodeAndProject(compileElement);
@ -442,13 +442,16 @@ function createViewClass(
ViewConstructorVars.parentInjector.name,
o.importType(resolveIdentifier(Identifiers.Injector))),
new o.FnParam(
ViewConstructorVars.declarationEl.name,
o.importType(resolveIdentifier(Identifiers.AppElement)))
ViewConstructorVars.parentView.name,
o.importType(resolveIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE])),
new o.FnParam(ViewConstructorVars.parentIndex.name, o.NUMBER_TYPE),
new o.FnParam(ViewConstructorVars.parentElement.name, o.DYNAMIC_TYPE)
];
var superConstructorArgs = [
o.variable(view.className), renderCompTypeVar, ViewTypeEnum.fromValue(view.viewType),
ViewConstructorVars.viewUtils, ViewConstructorVars.parentInjector,
ViewConstructorVars.declarationEl,
ViewConstructorVars.parentView, ViewConstructorVars.parentIndex,
ViewConstructorVars.parentElement,
ChangeDetectorStatusEnum.fromValue(getChangeDetectionMode(view))
];
if (view.genConfig.genDebugInfo) {
@ -507,8 +510,10 @@ function createViewFactory(
ViewConstructorVars.parentInjector.name,
o.importType(resolveIdentifier(Identifiers.Injector))),
new o.FnParam(
ViewConstructorVars.declarationEl.name,
o.importType(resolveIdentifier(Identifiers.AppElement)))
ViewConstructorVars.parentView.name,
o.importType(resolveIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE])),
new o.FnParam(ViewConstructorVars.parentIndex.name, o.NUMBER_TYPE),
new o.FnParam(ViewConstructorVars.parentElement.name, o.DYNAMIC_TYPE)
];
var initRenderCompTypeStmts: any[] = [];
var templateUrlInfo: string;
@ -553,8 +558,8 @@ function generateCreateMethod(view: CompileView): o.Statement[] {
var parentRenderNodeExpr: o.Expression = o.NULL_EXPR;
var parentRenderNodeStmts: any[] = [];
if (view.viewType === ViewType.COMPONENT) {
parentRenderNodeExpr = ViewProperties.renderer.callMethod(
'createViewRoot', [o.THIS_EXPR.prop('declarationAppElement').prop('nativeElement')]);
parentRenderNodeExpr =
ViewProperties.renderer.callMethod('createViewRoot', [o.THIS_EXPR.prop('parentElement')]);
parentRenderNodeStmts =
[parentRenderNodeVar.set(parentRenderNodeExpr)
.toDeclStmt(

View File

@ -24,7 +24,7 @@ export function main() {
const definedView = createCompileView({className: 'parentView'});
const callingView = createCompileView({className: 'childView', parent: definedView});
expect(getPropertyInView(expr, callingView, definedView))
.toEqual(o.THIS_EXPR.prop('parent').prop('someProp'));
.toEqual(o.THIS_EXPR.prop('parentView').prop('someProp'));
});
it('should access a known property in a parent view with cast', () => {
@ -32,7 +32,7 @@ export function main() {
const definedView = createCompileView({className: 'parentView', fields: ['someProp']});
const callingView = createCompileView({className: 'childView', parent: definedView});
expect(getPropertyInView(expr, callingView, definedView))
.toEqual(o.THIS_EXPR.prop('parent').cast(definedView.classType).prop('someProp'));
.toEqual(o.THIS_EXPR.prop('parentView').cast(definedView.classType).prop('someProp'));
});
it('should access a known property in a parent view with cast also for property chain expressions',
@ -41,7 +41,7 @@ export function main() {
const definedView = createCompileView({className: 'parentView', fields: ['someProp']});
const callingView = createCompileView({className: 'childView', parent: definedView});
expect(getPropertyInView(expr, callingView, definedView))
.toEqual(o.THIS_EXPR.prop('parent')
.toEqual(o.THIS_EXPR.prop('parentView')
.cast(definedView.classType)
.prop('someProp')
.prop('context'));

View File

@ -109,8 +109,7 @@ export class ComponentFactory<C> {
if (!projectableNodes) {
projectableNodes = [];
}
// Note: Host views don't need a declarationAppElement!
var hostView: AppView<any> = this._viewFactory(vu, injector, null);
var hostView: AppView<any> = this._viewFactory(vu, injector, null, null, null);
// TODO: implement this in the View class directly?!
// (behind a `if (this.type === ViewType.HOST)`)
// TODO: and pass the projectableNodes into `createHostView`

View File

@ -39,13 +39,10 @@ export class DebugContext implements RenderDebugInfo {
}
get componentRenderElement() {
var componentView = this._view;
while (isPresent(componentView.declarationAppElement) &&
componentView.type !== ViewType.COMPONENT) {
componentView = <DebugAppView<any>>componentView.declarationAppElement.parentView;
while (isPresent(componentView.parentView) && componentView.type !== ViewType.COMPONENT) {
componentView = <DebugAppView<any>>componentView.parentView;
}
return isPresent(componentView.declarationAppElement) ?
componentView.declarationAppElement.nativeElement :
null;
return componentView.parentElement;
}
get injector(): Injector { return this._view.injector(this._nodeIndex); }
get renderNode(): any {

View File

@ -47,7 +47,8 @@ export class TemplateRef_<C> extends TemplateRef<C> {
createEmbeddedView(context: C): EmbeddedViewRef<C> {
var view: AppView<C> = this._viewFactory(
this._appElement.parentView.viewUtils, this._appElement.parentInjector, this._appElement);
this._appElement.parentView.viewUtils, this._appElement.parentInjector,
this._appElement.parentView, this._appElement.index, this._appElement.nativeElement);
view.create(context || <any>{});
return view.ref;
}

View File

@ -52,13 +52,13 @@ export abstract class AppView<T> {
constructor(
public clazz: any, public componentType: RenderComponentType, public type: ViewType,
public viewUtils: ViewUtils, public parentInjector: Injector,
public declarationAppElement: AppElement, public cdMode: ChangeDetectorStatus) {
public viewUtils: ViewUtils, public parentInjector: Injector, public parentView: AppView<any>,
public parentIndex: number, public parentElement: any, public cdMode: ChangeDetectorStatus) {
this.ref = new ViewRef_(this);
if (type === ViewType.COMPONENT || type === ViewType.HOST) {
this.renderer = viewUtils.renderComponent(componentType);
} else {
this.renderer = declarationAppElement.parentView.renderer;
this.renderer = parentView.renderer;
}
}
@ -129,8 +129,7 @@ export abstract class AppView<T> {
if (this.cdMode === ChangeDetectorStatus.Destroyed) {
return;
}
var hostElement =
this.type === ViewType.COMPONENT ? this.declarationAppElement.nativeElement : null;
var hostElement = this.type === ViewType.COMPONENT ? this.parentElement : null;
if (this.disposables) {
for (var i = 0; i < this.disposables.length; i++) {
this.disposables[i]();
@ -171,10 +170,6 @@ export abstract class AppView<T> {
get changeDetectorRef(): ChangeDetectorRef { return this.ref; }
get parent(): AppView<any> {
return isPresent(this.declarationAppElement) ? this.declarationAppElement.parentView : null;
}
get flatRootNodes(): any[] {
const nodes: any[] = [];
this.visitRootNodesInternal(addToArray, nodes);
@ -188,13 +183,12 @@ export abstract class AppView<T> {
}
visitProjectedNodes<C>(ngContentIndex: number, cb: (node: any, ctx: C) => void, c: C): void {
const appEl = this.declarationAppElement;
switch (this.type) {
case ViewType.EMBEDDED:
appEl.parentView.visitProjectedNodes(ngContentIndex, cb, c);
this.parentView.visitProjectedNodes(ngContentIndex, cb, c);
break;
case ViewType.COMPONENT:
appEl.parentView.visitProjectableNodesInternal(appEl.index, ngContentIndex, cb, c);
this.parentView.visitProjectableNodesInternal(this.parentIndex, ngContentIndex, cb, c);
break;
}
}
@ -256,9 +250,11 @@ export abstract class AppView<T> {
if (c.cdMode === ChangeDetectorStatus.Checked) {
c.cdMode = ChangeDetectorStatus.CheckOnce;
}
let parentEl =
c.type === ViewType.COMPONENT ? c.declarationAppElement : c.viewContainerElement;
c = isPresent(parentEl) ? parentEl.parentView : null;
if (c.type === ViewType.COMPONENT) {
c = c.parentView;
} else {
c = c.viewContainerElement ? c.viewContainerElement.parentView : null;
}
}
}
@ -274,9 +270,11 @@ export class DebugAppView<T> extends AppView<T> {
constructor(
clazz: any, componentType: RenderComponentType, type: ViewType, viewUtils: ViewUtils,
parentInjector: Injector, declarationAppElement: AppElement, cdMode: ChangeDetectorStatus,
public staticNodeDebugInfos: StaticNodeDebugInfo[]) {
super(clazz, componentType, type, viewUtils, parentInjector, declarationAppElement, cdMode);
parentInjector: Injector, parentView: AppView<any>, parentIndex: number, parentNode: any,
cdMode: ChangeDetectorStatus, public staticNodeDebugInfos: StaticNodeDebugInfo[]) {
super(
clazz, componentType, type, viewUtils, parentInjector, parentView, parentIndex, parentNode,
cdMode);
}
create(context: T) {

View File

@ -27,10 +27,11 @@ class _View_TreeComponent_Host0 extends import1.AppView<any> {
_TreeComponent_0_4: _View_TreeComponent0;
constructor(
viewUtils: import4.ViewUtils, parentInjector: import5.Injector,
declarationEl: import2.AppElement) {
parentView: import1.AppView<any>, parentIndex: number, parentElement: any) {
super(
_View_TreeComponent_Host0, renderType_TreeComponent_Host, import6.ViewType.HOST, viewUtils,
parentInjector, declarationEl, import7.ChangeDetectorStatus.CheckAlways);
parentInjector, parentView, parentIndex, parentElement,
import7.ChangeDetectorStatus.CheckAlways);
}
createInternal(rootSelector: string): import9.ComponentRef<any> {
this._el_0 = import4.selectOrCreateRenderHostElement(
@ -53,12 +54,14 @@ class _View_TreeComponent_Host0 extends import1.AppView<any> {
}
function viewFactory_TreeComponent_Host0(
viewUtils: import4.ViewUtils, parentInjector: import5.Injector,
declarationEl: import2.AppElement): import1.AppView<any> {
parentView: import1.AppView<any>, parentIndex: number,
parentElement: any): import1.AppView<any> {
if ((renderType_TreeComponent_Host === (null as any))) {
(renderType_TreeComponent_Host =
viewUtils.createRenderComponentType('', 0, import8.ViewEncapsulation.None, [], {}));
}
return new _View_TreeComponent_Host0(viewUtils, parentInjector, declarationEl);
return new _View_TreeComponent_Host0(
viewUtils, parentInjector, parentView, parentIndex, parentElement);
}
export const TreeComponentNgFactory: import9.ComponentFactory<import3.TreeComponent> =
new import9.ComponentFactory<import3.TreeComponent>(

View File

@ -30,17 +30,18 @@ class _View_TreeRootComponent_Host0 extends import1.AppView<any> {
_TreeRootComponent_0_4_View: any;
constructor(
viewUtils: import4.ViewUtils, parentInjector: import5.Injector,
declarationEl: import2.AppElement) {
parentView: import1.AppView<any>, parentIndex: number, parentElement: any) {
super(
_View_TreeRootComponent_Host0, renderType_TreeRootComponent_Host, import6.ViewType.HOST,
viewUtils, parentInjector, declarationEl, import7.ChangeDetectorStatus.CheckAlways);
viewUtils, parentInjector, parentView, parentIndex, parentElement,
import7.ChangeDetectorStatus.CheckAlways);
}
createInternal(rootSelector: string): import9.ComponentRef<any> {
this._el_0 = import4.selectOrCreateRenderHostElement(
this.renderer, 'tree', import4.EMPTY_INLINE_ARRAY, rootSelector, (null as any));
this._appEl_0 = new import2.AppElement(0, (null as any), this, this._el_0);
this._TreeRootComponent_0_4_View =
viewFactory_TreeRootComponent0(this.viewUtils, this.injector(0), this._appEl_0);
viewFactory_TreeRootComponent0(this.viewUtils, this.injector(0), this, 0, this._el_0);
this._TreeRootComponent_0_4 = new import3.TreeRootComponent();
this._TreeRootComponent_0_4_View.create(this._TreeRootComponent_0_4, (null as any));
this.init([].concat([this._el_0]), [this._el_0], []);
@ -59,12 +60,14 @@ class _View_TreeRootComponent_Host0 extends import1.AppView<any> {
}
function viewFactory_TreeRootComponent_Host0(
viewUtils: import4.ViewUtils, parentInjector: import5.Injector,
declarationEl: import2.AppElement): import1.AppView<any> {
parentView: import1.AppView<any>, parentIndex: number,
parentElement: any): import1.AppView<any> {
if ((renderType_TreeRootComponent_Host === (null as any))) {
(renderType_TreeRootComponent_Host =
viewUtils.createRenderComponentType('', 0, import8.ViewEncapsulation.None, [], {}));
}
return new _View_TreeRootComponent_Host0(viewUtils, parentInjector, declarationEl);
return new _View_TreeRootComponent_Host0(
viewUtils, parentInjector, parentView, parentIndex, parentElement);
}
export const TreeRootComponentNgFactory: import9.ComponentFactory<import3.TreeRootComponent> =
new import9.ComponentFactory<import3.TreeRootComponent>(
@ -79,14 +82,14 @@ class _View_TreeRootComponent0 extends import1.AppView<import3.TreeRootComponent
/*private*/ _expr_0: any;
constructor(
viewUtils: import4.ViewUtils, parentInjector: import5.Injector,
declarationEl: import2.AppElement) {
parentView: import1.AppView<any>, parentIndex: number, parentElement: any) {
super(
_View_TreeRootComponent0, renderType_TreeRootComponent, import6.ViewType.COMPONENT,
viewUtils, parentInjector, declarationEl, import7.ChangeDetectorStatus.CheckAlways);
viewUtils, parentInjector, parentView, parentIndex, parentElement,
import7.ChangeDetectorStatus.CheckAlways);
}
createInternal(rootSelector: string): import9.ComponentRef<any> {
const parentRenderNode: any =
this.renderer.createViewRoot(this.declarationAppElement.nativeElement);
const parentRenderNode: any = this.renderer.createViewRoot(this.parentElement);
this._anchor_0 = this.renderer.createTemplateAnchor(parentRenderNode, (null as any));
this._appEl_0 = new import2.AppElement(0, (null as any), this, this._anchor_0);
this._TemplateRef_0_5 =
@ -116,23 +119,26 @@ class _View_TreeRootComponent0 extends import1.AppView<import3.TreeRootComponent
}
export function viewFactory_TreeRootComponent0(
viewUtils: import4.ViewUtils, parentInjector: import5.Injector,
declarationEl: import2.AppElement): import1.AppView<import3.TreeRootComponent> {
parentView: import1.AppView<any>, parentIndex: number,
parentElement: any): import1.AppView<import3.TreeRootComponent> {
if ((renderType_TreeRootComponent === (null as any))) {
(renderType_TreeRootComponent = viewUtils.createRenderComponentType(
'/Users/tbosch/projects/conf-demos/ngc-demo/src/ng2_static/root_tree.ts class TreeRootComponent - inline template',
0, import8.ViewEncapsulation.None, styles_TreeRootComponent, {}));
}
return new _View_TreeRootComponent0(viewUtils, parentInjector, declarationEl);
return new _View_TreeRootComponent0(
viewUtils, parentInjector, parentView, parentIndex, parentElement);
}
class _View_TreeRootComponent1 extends import1.AppView<any> {
_el_0: any;
_TreeComponent0_0_4View: any;
constructor(
viewUtils: import4.ViewUtils, parentInjector: import5.Injector,
declarationEl: import2.AppElement) {
parentView: import1.AppView<any>, parentIndex: number, parentElement: any) {
super(
_View_TreeRootComponent1, renderType_TreeRootComponent, import6.ViewType.EMBEDDED,
viewUtils, parentInjector, declarationEl, import7.ChangeDetectorStatus.CheckAlways);
viewUtils, parentInjector, parentView, parentIndex, parentElement,
import7.ChangeDetectorStatus.CheckAlways);
}
createInternal(rootSelector: string): import9.ComponentRef<any> {
this._el_0 = this.renderer.createElement((null as any), 'tree0', (null as any));
@ -142,13 +148,15 @@ class _View_TreeRootComponent1 extends import1.AppView<any> {
}
destroyInternal() { this._TreeComponent0_0_4View.destroyInternal(); }
detectChangesInternal(throwOnChange: boolean): void {
this._TreeComponent0_0_4View.updateData(this.parent.context.data);
this._TreeComponent0_0_4View.updateData(this.parentView.context.data);
this._TreeComponent0_0_4View.detectChangesInternal(throwOnChange);
}
visitRootNodesInternal(cb: any, context: any) { cb(this._el_0, context); }
}
function viewFactory_TreeRootComponent1(
viewUtils: import4.ViewUtils, parentInjector: import5.Injector,
declarationEl: import2.AppElement): import1.AppView<any> {
return new _View_TreeRootComponent1(viewUtils, parentInjector, declarationEl);
parentView: import1.AppView<any>, parentIndex: number,
parentElement: any): import1.AppView<any> {
return new _View_TreeRootComponent1(
viewUtils, parentInjector, parentView, parentIndex, parentElement);
}