Skip to content

Commit 7470ad1

Browse files
committed
refactor(compiler): various cleanups
- use `$implicit` variable value correctly - handle `ng-non-bindable` correctly - add some more assertions to `TemplateCompiler` - make `CompiledTemplate` const - fix default value for `@Directive.moduleId` - add new compiler to application bindings BREAKING CHANGE: - `Compiler.compileInHost` and all methods of `DynamicComponentLoader` don’t take `Binding` any more, only `Type`s. This is in preparation for the new compiler which does not support this. Part of angular#3605 Closes angular#4346
1 parent bffa2cb commit 7470ad1

29 files changed

+494
-286
lines changed

modules/angular2/src/compiler/command_compiler.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ import {escapeSingleQuoteString} from './util';
3535
import {Injectable} from 'angular2/src/core/di';
3636

3737
export var TEMPLATE_COMMANDS_MODULE_REF = moduleRef('angular2/src/core/compiler/template_commands');
38-
const IMPLICIT_VAR = '%implicit';
38+
39+
const IMPLICIT_TEMPLATE_VAR = '\$implicit';
3940

4041
@Injectable()
4142
export class CommandCompiler {
@@ -207,7 +208,7 @@ class CommandBuilderVisitor<R> implements TemplateAstVisitor {
207208
var variableNameAndValues = [];
208209
ast.vars.forEach((varAst) => {
209210
variableNameAndValues.push(varAst.name);
210-
variableNameAndValues.push(varAst.value);
211+
variableNameAndValues.push(varAst.value.length > 0 ? varAst.value : IMPLICIT_TEMPLATE_VAR);
211212
});
212213
var directives = [];
213214
ListWrapper.forEachWithIndex(ast.directives, (directiveAst: DirectiveAst, index: number) => {
@@ -227,7 +228,7 @@ class CommandBuilderVisitor<R> implements TemplateAstVisitor {
227228
if (isBlank(component)) {
228229
ast.exportAsVars.forEach((varAst) => {
229230
variableNameAndValues.push(varAst.name);
230-
variableNameAndValues.push(IMPLICIT_VAR);
231+
variableNameAndValues.push(null);
231232
});
232233
}
233234
var directives = [];

modules/angular2/src/compiler/compiler.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,31 @@ export {
55
CompileTemplateMetadata
66
} from './directive_metadata';
77
export {SourceModule, SourceWithImports} from './source_module';
8+
9+
import {assertionsEnabled, Type} from 'angular2/src/core/facade/lang';
10+
import {bind, Binding} from 'angular2/src/core/di';
11+
import {TemplateParser} from 'angular2/src/compiler/template_parser';
12+
import {HtmlParser} from 'angular2/src/compiler/html_parser';
13+
import {TemplateNormalizer} from 'angular2/src/compiler/template_normalizer';
14+
import {RuntimeMetadataResolver} from 'angular2/src/compiler/runtime_metadata';
15+
import {ChangeDetectionCompiler} from 'angular2/src/compiler/change_detector_compiler';
16+
import {StyleCompiler} from 'angular2/src/compiler/style_compiler';
17+
import {CommandCompiler} from 'angular2/src/compiler/command_compiler';
18+
import {TemplateCompiler} from 'angular2/src/compiler/template_compiler';
19+
import {ChangeDetectorGenConfig} from 'angular2/src/core/change_detection/change_detection';
20+
21+
export function compilerBindings(): Array<Type | Binding | any[]> {
22+
return [
23+
HtmlParser,
24+
TemplateParser,
25+
TemplateNormalizer,
26+
RuntimeMetadataResolver,
27+
StyleCompiler,
28+
CommandCompiler,
29+
ChangeDetectionCompiler,
30+
bind(ChangeDetectorGenConfig)
31+
.toValue(
32+
new ChangeDetectorGenConfig(assertionsEnabled(), assertionsEnabled(), false, true)),
33+
TemplateCompiler,
34+
];
35+
}

modules/angular2/src/compiler/html_parser.ts

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,7 @@ function parseElement(element: Element, indexInParent: number, parentSourceInfo:
5757
var sourceInfo = `${parentSourceInfo} > ${nodeName}:nth-child(${indexInParent})`;
5858
var attrs = parseAttrs(element, sourceInfo);
5959

60-
var childNodes;
61-
if (ignoreChildren(attrs)) {
62-
childNodes = [];
63-
} else {
64-
childNodes = parseChildNodes(element, sourceInfo);
65-
}
60+
var childNodes = parseChildNodes(element, sourceInfo);
6661
return new HtmlElementAst(nodeName, attrs, childNodes, sourceInfo);
6762
}
6863

@@ -100,16 +95,6 @@ function parseChildNodes(element: Element, parentSourceInfo: string): HtmlAst[]
10095
return result;
10196
}
10297

103-
function ignoreChildren(attrs: HtmlAttrAst[]): boolean {
104-
for (var i = 0; i < attrs.length; i++) {
105-
var a = attrs[i];
106-
if (a.name == NG_NON_BINDABLE) {
107-
return true;
108-
}
109-
}
110-
return false;
111-
}
112-
11398
class UnparseVisitor implements HtmlAstVisitor {
11499
visitElement(ast: HtmlElementAst, parts: string[]): any {
115100
parts.push(`<${ast.name}`);

modules/angular2/src/compiler/style_compiler.ts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {CompileTypeMetadata, CompileDirectiveMetadata} from './directive_metadata';
1+
import {CompileTypeMetadata, CompileTemplateMetadata} from './directive_metadata';
22
import {SourceModule, SourceExpression, moduleRef} from './source_module';
33
import {ViewEncapsulation} from 'angular2/src/core/render/api';
44
import {XHR} from 'angular2/src/core/render/xhr';
@@ -29,27 +29,28 @@ export class StyleCompiler {
2929

3030
constructor(private _xhr: XHR, private _urlResolver: UrlResolver) {}
3131

32-
compileComponentRuntime(component: CompileDirectiveMetadata): Promise<string[]> {
33-
var styles = component.template.styles;
34-
var styleAbsUrls = component.template.styleUrls;
32+
compileComponentRuntime(type: CompileTypeMetadata,
33+
template: CompileTemplateMetadata): Promise<string[]> {
34+
var styles = template.styles;
35+
var styleAbsUrls = template.styleUrls;
3536
return this._loadStyles(styles, styleAbsUrls,
36-
component.template.encapsulation === ViewEncapsulation.Emulated)
37-
.then(styles => styles.map(style => StringWrapper.replaceAll(style, COMPONENT_REGEX,
38-
`${component.type.id}`)));
37+
template.encapsulation === ViewEncapsulation.Emulated)
38+
.then(styles => styles.map(
39+
style => StringWrapper.replaceAll(style, COMPONENT_REGEX, `${type.id}`)));
3940
}
4041

41-
compileComponentCodeGen(component: CompileDirectiveMetadata): SourceExpression {
42-
var shim = component.template.encapsulation === ViewEncapsulation.Emulated;
42+
compileComponentCodeGen(type: CompileTypeMetadata,
43+
template: CompileTemplateMetadata): SourceExpression {
44+
var shim = template.encapsulation === ViewEncapsulation.Emulated;
4345
var suffix;
4446
if (shim) {
45-
var componentId = `${ component.type.id}`;
47+
var componentId = `${ type.id}`;
4648
suffix =
4749
codeGenMapArray(['style'], `style${codeGenReplaceAll(COMPONENT_VARIABLE, componentId)}`);
4850
} else {
4951
suffix = '';
5052
}
51-
return this._styleCodeGen(component.template.styles, component.template.styleUrls, shim,
52-
suffix);
53+
return this._styleCodeGen(template.styles, template.styleUrls, shim, suffix);
5354
}
5455

5556
compileStylesheetCodeGen(moduleId: string, cssText: string): SourceModule[] {

modules/angular2/src/compiler/template_compiler.ts

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {Type, Json, isBlank, stringify} from 'angular2/src/core/facade/lang';
2+
import {BaseException} from 'angular2/src/core/facade/exceptions';
23
import {ListWrapper, SetWrapper} from 'angular2/src/core/facade/collection';
34
import {PromiseWrapper, Promise} from 'angular2/src/core/facade/async';
45
import {CompiledTemplate, TemplateCmd} from 'angular2/src/core/compiler/template_commands';
@@ -58,18 +59,12 @@ export class TemplateCompiler {
5859
}));
5960
}
6061

61-
serializeDirectiveMetadata(metadata: CompileDirectiveMetadata): string {
62-
return Json.stringify(metadata.toJson());
63-
}
64-
65-
deserializeDirectiveMetadata(data: string): CompileDirectiveMetadata {
66-
return CompileDirectiveMetadata.fromJson(Json.parse(data));
67-
}
68-
6962
compileHostComponentRuntime(type: Type): Promise<CompiledTemplate> {
7063
var compMeta: CompileDirectiveMetadata = this._runtimeMetadataResolver.getMetadata(type);
64+
assertComponent(compMeta);
7165
var hostMeta: CompileDirectiveMetadata =
7266
createHostComponentMeta(compMeta.type, compMeta.selector);
67+
7368
this._compileComponentRuntime(hostMeta, [compMeta], new Set());
7469
return this._compiledTemplateDone.get(hostMeta.type.id);
7570
}
@@ -93,28 +88,30 @@ export class TemplateCompiler {
9388
new CompiledTemplate(compMeta.type.id, () => [changeDetectorFactory, commands, styles]);
9489
this._compiledTemplateCache.set(compMeta.type.id, compiledTemplate);
9590
compilingComponentIds.add(compMeta.type.id);
96-
done = PromiseWrapper.all([<any>this._styleCompiler.compileComponentRuntime(compMeta)].concat(
97-
viewDirectives.map(
98-
dirMeta => this.normalizeDirectiveMetadata(dirMeta))))
99-
.then((stylesAndNormalizedViewDirMetas: any[]) => {
100-
var childPromises = [];
101-
var normalizedViewDirMetas = stylesAndNormalizedViewDirMetas.slice(1);
102-
var parsedTemplate = this._templateParser.parse(
103-
compMeta.template.template, normalizedViewDirMetas, compMeta.type.name);
104-
105-
var changeDetectorFactories = this._cdCompiler.compileComponentRuntime(
106-
compMeta.type, compMeta.changeDetection, parsedTemplate);
107-
changeDetectorFactory = changeDetectorFactories[0];
108-
styles = stylesAndNormalizedViewDirMetas[0];
109-
commands = this._compileCommandsRuntime(compMeta, parsedTemplate,
110-
changeDetectorFactories,
111-
compilingComponentIds, childPromises);
112-
return PromiseWrapper.all(childPromises);
113-
})
114-
.then((_) => {
115-
SetWrapper.delete(compilingComponentIds, compMeta.type.id);
116-
return compiledTemplate;
117-
});
91+
done =
92+
PromiseWrapper
93+
.all([
94+
<any>this._styleCompiler.compileComponentRuntime(compMeta.type, compMeta.template)
95+
].concat(viewDirectives.map(dirMeta => this.normalizeDirectiveMetadata(dirMeta))))
96+
.then((stylesAndNormalizedViewDirMetas: any[]) => {
97+
var childPromises = [];
98+
var normalizedViewDirMetas = stylesAndNormalizedViewDirMetas.slice(1);
99+
var parsedTemplate = this._templateParser.parse(
100+
compMeta.template.template, normalizedViewDirMetas, compMeta.type.name);
101+
102+
var changeDetectorFactories = this._cdCompiler.compileComponentRuntime(
103+
compMeta.type, compMeta.changeDetection, parsedTemplate);
104+
changeDetectorFactory = changeDetectorFactories[0];
105+
styles = stylesAndNormalizedViewDirMetas[0];
106+
commands =
107+
this._compileCommandsRuntime(compMeta, parsedTemplate, changeDetectorFactories,
108+
compilingComponentIds, childPromises);
109+
return PromiseWrapper.all(childPromises);
110+
})
111+
.then((_) => {
112+
SetWrapper.delete(compilingComponentIds, compMeta.type.id);
113+
return compiledTemplate;
114+
});
118115
this._compiledTemplateDone.set(compMeta.type.id, done);
119116
}
120117
return compiledTemplate;
@@ -148,6 +145,7 @@ export class TemplateCompiler {
148145
var componentMetas: CompileDirectiveMetadata[] = [];
149146
components.forEach(componentWithDirs => {
150147
var compMeta = <CompileDirectiveMetadata>componentWithDirs.component;
148+
assertComponent(compMeta);
151149
componentMetas.push(compMeta);
152150
this._processTemplateCodeGen(compMeta,
153151
<CompileDirectiveMetadata[]>componentWithDirs.directives,
@@ -174,7 +172,7 @@ export class TemplateCompiler {
174172
private _processTemplateCodeGen(compMeta: CompileDirectiveMetadata,
175173
directives: CompileDirectiveMetadata[],
176174
targetDeclarations: string[], targetTemplateArguments: any[][]) {
177-
var styleExpr = this._styleCompiler.compileComponentCodeGen(compMeta);
175+
var styleExpr = this._styleCompiler.compileComponentCodeGen(compMeta.type, compMeta.template);
178176
var parsedTemplate =
179177
this._templateParser.parse(compMeta.template.template, directives, compMeta.type.name);
180178
var changeDetectorsExprs = this._cdCompiler.compileComponentCodeGen(
@@ -197,6 +195,12 @@ export class NormalizedComponentWithViewDirectives {
197195
public directives: CompileDirectiveMetadata[]) {}
198196
}
199197

198+
function assertComponent(meta: CompileDirectiveMetadata) {
199+
if (!meta.isComponent) {
200+
throw new BaseException(`Could not compile '${meta.type.name}' because it is not a component.`);
201+
}
202+
}
203+
200204
function templateVariableName(type: CompileTypeMetadata): string {
201205
return `${type.name}Template`;
202206
}

modules/angular2/src/compiler/template_normalizer.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
CompileTemplateMetadata
55
} from './directive_metadata';
66
import {isPresent, isBlank} from 'angular2/src/core/facade/lang';
7+
import {BaseException} from 'angular2/src/core/facade/exceptions';
78
import {Promise, PromiseWrapper} from 'angular2/src/core/facade/async';
89

910
import {XHR} from 'angular2/src/core/render/xhr';
@@ -34,11 +35,13 @@ export class TemplateNormalizer {
3435
if (isPresent(template.template)) {
3536
return PromiseWrapper.resolve(this.normalizeLoadedTemplate(
3637
directiveType, template, template.template, directiveType.moduleId));
37-
} else {
38+
} else if (isPresent(template.templateUrl)) {
3839
var sourceAbsUrl = this._urlResolver.resolve(directiveType.moduleId, template.templateUrl);
3940
return this._xhr.get(sourceAbsUrl)
4041
.then(templateContent => this.normalizeLoadedTemplate(directiveType, template,
4142
templateContent, sourceAbsUrl));
43+
} else {
44+
throw new BaseException(`No template specified for component ${directiveType.name}`);
4245
}
4346
}
4447

@@ -79,12 +82,15 @@ class TemplatePreparseVisitor implements HtmlAstVisitor {
7982
ngContentSelectors: string[] = [];
8083
styles: string[] = [];
8184
styleUrls: string[] = [];
85+
ngNonBindableStackCount: number = 0;
8286

8387
visitElement(ast: HtmlElementAst, context: any): any {
8488
var preparsedElement = preparseElement(ast);
8589
switch (preparsedElement.type) {
8690
case PreparsedElementType.NG_CONTENT:
87-
this.ngContentSelectors.push(preparsedElement.selectAttr);
91+
if (this.ngNonBindableStackCount === 0) {
92+
this.ngContentSelectors.push(preparsedElement.selectAttr);
93+
}
8894
break;
8995
case PreparsedElementType.STYLE:
9096
var textContent = '';
@@ -99,8 +105,12 @@ class TemplatePreparseVisitor implements HtmlAstVisitor {
99105
this.styleUrls.push(preparsedElement.hrefAttr);
100106
break;
101107
}
102-
if (preparsedElement.type !== PreparsedElementType.NON_BINDABLE) {
103-
htmlVisitAll(this, ast.children);
108+
if (preparsedElement.nonBindable) {
109+
this.ngNonBindableStackCount++;
110+
}
111+
htmlVisitAll(this, ast.children);
112+
if (preparsedElement.nonBindable) {
113+
this.ngNonBindableStackCount--;
104114
}
105115
return null;
106116
}

0 commit comments

Comments
 (0)