Skip to content

Commit 0246b2a

Browse files
committed
feat(compiler): support creating template commands
Closes angular#4142
1 parent 71cbb49 commit 0246b2a

File tree

13 files changed

+1324
-166
lines changed

13 files changed

+1324
-166
lines changed

modules/angular2/src/compiler/api.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ export class TemplateMetadata {
134134
this.ngContentSelectors = ngContentSelectors;
135135
}
136136

137-
static fromJson(data: StringMap<string, any>):TemplateMetadata {
137+
static fromJson(data: StringMap<string, any>): TemplateMetadata {
138138
return new TemplateMetadata({
139139
encapsulation: isPresent(data['encapsulation']) ?
140140
viewEncapsulationFromJson(data['encapsulation']) :

modules/angular2/src/compiler/change_definition_factory.ts

Lines changed: 42 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -36,47 +36,43 @@ import {
3636
export function createChangeDetectorDefinitions(
3737
componentType: TypeMetadata, componentStrategy: ChangeDetectionStrategy,
3838
genConfig: ChangeDetectorGenConfig, parsedTemplate: TemplateAst[]): ChangeDetectorDefinition[] {
39-
var visitor = new ProtoViewVisitor(componentStrategy);
39+
var pvVisitors = [];
40+
var visitor = new ProtoViewVisitor(null, pvVisitors, componentStrategy);
4041
templateVisitAll(visitor, parsedTemplate);
41-
return createChangeDefinitions(visitor.allProtoViews, componentType, genConfig);
42+
return createChangeDefinitions(pvVisitors, componentType, genConfig);
4243
}
4344

4445
class ProtoViewVisitor implements TemplateAstVisitor {
45-
viewCount: number = 0;
46-
protoViewStack: ProtoViewVisitorData[] = [];
47-
allProtoViews: ProtoViewVisitorData[] = [];
48-
49-
constructor(componentStrategy: ChangeDetectionStrategy) {
50-
this._beginProtoView(new ProtoViewVisitorData(null, componentStrategy, this.viewCount++));
51-
}
52-
53-
private _beginProtoView(data: ProtoViewVisitorData) {
54-
this.protoViewStack.push(data);
55-
this.allProtoViews.push(data);
56-
}
46+
viewIndex: number;
47+
boundTextCount: number = 0;
48+
boundElementCount: number = 0;
49+
variableNames: string[] = [];
50+
bindingRecords: BindingRecord[] = [];
51+
eventRecords: BindingRecord[] = [];
52+
directiveRecords: DirectiveRecord[] = [];
5753

58-
get currentProtoView(): ProtoViewVisitorData {
59-
return this.protoViewStack[this.protoViewStack.length - 1];
54+
constructor(public parent: ProtoViewVisitor, public allVisitors: ProtoViewVisitor[],
55+
public strategy: ChangeDetectionStrategy) {
56+
this.viewIndex = allVisitors.length;
57+
allVisitors.push(this);
6058
}
6159

6260
visitEmbeddedTemplate(ast: EmbeddedTemplateAst, context: any): any {
63-
this.currentProtoView.boundElementCount++;
61+
this.boundElementCount++;
6462
templateVisitAll(this, ast.directives);
6563

66-
this.viewCount++;
67-
this._beginProtoView(new ProtoViewVisitorData(
68-
this.currentProtoView, ChangeDetectionStrategy.Default, this.viewCount - 1));
64+
var childVisitor =
65+
new ProtoViewVisitor(this, this.allVisitors, ChangeDetectionStrategy.Default);
6966
// Attention: variables present on an embedded template count towards
7067
// the embedded template and not the template anchor!
71-
templateVisitAll(this, ast.vars);
72-
templateVisitAll(this, ast.children);
73-
this.protoViewStack.pop();
68+
templateVisitAll(childVisitor, ast.vars);
69+
templateVisitAll(childVisitor, ast.children);
7470
return null;
7571
}
7672

7773
visitElement(ast: ElementAst, context: any): any {
7874
if (ast.isBound()) {
79-
this.currentProtoView.boundElementCount++;
75+
this.boundElementCount++;
8076
}
8177
templateVisitAll(this, ast.properties, null);
8278
templateVisitAll(this, ast.events);
@@ -91,22 +87,21 @@ class ProtoViewVisitor implements TemplateAstVisitor {
9187
visitNgContent(ast: NgContentAst, context: any): any { return null; }
9288

9389
visitVariable(ast: VariableAst, context: any): any {
94-
this.currentProtoView.variableNames.push(ast.name);
90+
this.variableNames.push(ast.name);
9591
return null;
9692
}
9793

9894
visitEvent(ast: BoundEventAst, directiveRecord: DirectiveRecord): any {
9995
var bindingRecord =
10096
isPresent(directiveRecord) ?
10197
BindingRecord.createForHostEvent(ast.handler, ast.name, directiveRecord) :
102-
BindingRecord.createForEvent(ast.handler, ast.name,
103-
this.currentProtoView.boundElementCount - 1);
104-
this.currentProtoView.eventRecords.push(bindingRecord);
98+
BindingRecord.createForEvent(ast.handler, ast.name, this.boundElementCount - 1);
99+
this.eventRecords.push(bindingRecord);
105100
return null;
106101
}
107102

108103
visitElementProperty(ast: BoundElementPropertyAst, directiveRecord: DirectiveRecord): any {
109-
var boundElementIndex = this.currentProtoView.boundElementCount - 1;
104+
var boundElementIndex = this.boundElementCount - 1;
110105
var dirIndex = isPresent(directiveRecord) ? directiveRecord.directiveIndex : null;
111106
var bindingRecord;
112107
if (ast.type === PropertyBindingType.Property) {
@@ -130,20 +125,18 @@ class ProtoViewVisitor implements TemplateAstVisitor {
130125
BindingRecord.createForHostStyle(dirIndex, ast.value, ast.name, ast.unit) :
131126
BindingRecord.createForElementStyle(ast.value, boundElementIndex, ast.name, ast.unit);
132127
}
133-
this.currentProtoView.bindingRecords.push(bindingRecord);
128+
this.bindingRecords.push(bindingRecord);
134129
return null;
135130
}
136131
visitAttr(ast: AttrAst, context: any): any { return null; }
137132
visitBoundText(ast: BoundTextAst, context: any): any {
138-
var boundTextIndex = this.currentProtoView.boundTextCount++;
139-
this.currentProtoView.bindingRecords.push(
140-
BindingRecord.createForTextNode(ast.value, boundTextIndex));
133+
var boundTextIndex = this.boundTextCount++;
134+
this.bindingRecords.push(BindingRecord.createForTextNode(ast.value, boundTextIndex));
141135
return null;
142136
}
143137
visitText(ast: TextAst, context: any): any { return null; }
144138
visitDirective(ast: DirectiveAst, directiveIndexAsNumber: number): any {
145-
var directiveIndex =
146-
new DirectiveIndex(this.currentProtoView.boundElementCount - 1, directiveIndexAsNumber);
139+
var directiveIndex = new DirectiveIndex(this.boundElementCount - 1, directiveIndexAsNumber);
147140
var directiveMetadata = ast.directive;
148141
var changeDetectionMeta = directiveMetadata.changeDetection;
149142
var directiveRecord = new DirectiveRecord({
@@ -157,10 +150,10 @@ class ProtoViewVisitor implements TemplateAstVisitor {
157150
callOnInit: changeDetectionMeta.callOnInit,
158151
changeDetection: changeDetectionMeta.changeDetection
159152
});
160-
this.currentProtoView.directiveRecords.push(directiveRecord);
153+
this.directiveRecords.push(directiveRecord);
161154

162155
templateVisitAll(this, ast.properties, directiveRecord);
163-
var bindingRecords = this.currentProtoView.bindingRecords;
156+
var bindingRecords = this.bindingRecords;
164157
if (directiveRecord.callOnChanges) {
165158
bindingRecords.push(BindingRecord.createDirectiveOnChanges(directiveRecord));
166159
}
@@ -178,39 +171,29 @@ class ProtoViewVisitor implements TemplateAstVisitor {
178171
// TODO: these setters should eventually be created by change detection, to make
179172
// it monomorphic!
180173
var setter = reflector.setter(ast.directiveName);
181-
this.currentProtoView.bindingRecords.push(
174+
this.bindingRecords.push(
182175
BindingRecord.createForDirective(ast.value, ast.directiveName, setter, directiveRecord));
183176
return null;
184177
}
185178
}
186179

187-
class ProtoViewVisitorData {
188-
boundTextCount: number = 0;
189-
boundElementCount: number = 0;
190-
variableNames: string[] = [];
191-
bindingRecords: BindingRecord[] = [];
192-
eventRecords: BindingRecord[] = [];
193-
directiveRecords: DirectiveRecord[] = [];
194-
constructor(public parent: ProtoViewVisitorData, public strategy: ChangeDetectionStrategy,
195-
public viewIndex: number) {}
196-
}
197180

198-
function createChangeDefinitions(pvDatas: ProtoViewVisitorData[], componentType: TypeMetadata,
181+
function createChangeDefinitions(pvVisitors: ProtoViewVisitor[], componentType: TypeMetadata,
199182
genConfig: ChangeDetectorGenConfig): ChangeDetectorDefinition[] {
200-
var pvVariableNames = _collectNestedProtoViewsVariableNames(pvDatas);
201-
return pvDatas.map(pvData => {
202-
var viewType = pvData.viewIndex === 0 ? 'component' : 'embedded';
203-
var id = _protoViewId(componentType, pvData.viewIndex, viewType);
204-
return new ChangeDetectorDefinition(id, pvData.strategy, pvVariableNames[pvData.viewIndex],
205-
pvData.bindingRecords, pvData.eventRecords,
206-
pvData.directiveRecords, genConfig);
183+
var pvVariableNames = _collectNestedProtoViewsVariableNames(pvVisitors);
184+
return pvVisitors.map(pvVisitor => {
185+
var viewType = pvVisitor.viewIndex === 0 ? 'component' : 'embedded';
186+
var id = _protoViewId(componentType, pvVisitor.viewIndex, viewType);
187+
return new ChangeDetectorDefinition(
188+
id, pvVisitor.strategy, pvVariableNames[pvVisitor.viewIndex], pvVisitor.bindingRecords,
189+
pvVisitor.eventRecords, pvVisitor.directiveRecords, genConfig);
207190

208191
});
209192
}
210193

211-
function _collectNestedProtoViewsVariableNames(pvs: ProtoViewVisitorData[]): string[][] {
212-
var nestedPvVariableNames: string[][] = ListWrapper.createFixedSize(pvs.length);
213-
pvs.forEach((pv) => {
194+
function _collectNestedProtoViewsVariableNames(pvVisitors: ProtoViewVisitor[]): string[][] {
195+
var nestedPvVariableNames: string[][] = ListWrapper.createFixedSize(pvVisitors.length);
196+
pvVisitors.forEach((pv) => {
214197
var parentVariableNames: string[] =
215198
isPresent(pv.parent) ? nestedPvVariableNames[pv.parent.viewIndex] : [];
216199
nestedPvVariableNames[pv.viewIndex] = parentVariableNames.concat(pv.variableNames);

0 commit comments

Comments
 (0)