refactor(compiler): don’t require `id` in metadata and use `appId`
The output of the compiler has to be the same given the same input. Requiring a unique id for every type already during compilation makes it hard to parallelize compilation. Part of #3605 Closes #4397
This commit is contained in:
parent
cd0e9c9cd4
commit
8ff65a30c7
|
@ -8,7 +8,8 @@ import {
|
||||||
endElement,
|
endElement,
|
||||||
beginComponent,
|
beginComponent,
|
||||||
endComponent,
|
endComponent,
|
||||||
embeddedTemplate
|
embeddedTemplate,
|
||||||
|
CompiledTemplate
|
||||||
} from 'angular2/src/core/compiler/template_commands';
|
} from 'angular2/src/core/compiler/template_commands';
|
||||||
import {
|
import {
|
||||||
TemplateAst,
|
TemplateAst,
|
||||||
|
@ -30,7 +31,12 @@ import {CompileTypeMetadata, CompileDirectiveMetadata} from './directive_metadat
|
||||||
import {SourceExpressions, SourceExpression, moduleRef} from './source_module';
|
import {SourceExpressions, SourceExpression, moduleRef} from './source_module';
|
||||||
|
|
||||||
import {ViewEncapsulation} from 'angular2/src/core/render/api';
|
import {ViewEncapsulation} from 'angular2/src/core/render/api';
|
||||||
import {shimHostAttribute, shimContentAttribute} from './style_compiler';
|
import {
|
||||||
|
shimHostAttribute,
|
||||||
|
shimContentAttribute,
|
||||||
|
shimContentAttributeExpr,
|
||||||
|
shimHostAttributeExpr
|
||||||
|
} from './style_compiler';
|
||||||
import {escapeSingleQuoteString} from './util';
|
import {escapeSingleQuoteString} from './util';
|
||||||
import {Injectable} from 'angular2/src/core/di';
|
import {Injectable} from 'angular2/src/core/di';
|
||||||
|
|
||||||
|
@ -40,21 +46,25 @@ const IMPLICIT_TEMPLATE_VAR = '\$implicit';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CommandCompiler {
|
export class CommandCompiler {
|
||||||
compileComponentRuntime(component: CompileDirectiveMetadata, template: TemplateAst[],
|
compileComponentRuntime(component: CompileDirectiveMetadata, appId: string, templateId: number,
|
||||||
changeDetectorFactories: Function[],
|
template: TemplateAst[], changeDetectorFactories: Function[],
|
||||||
componentTemplateFactory: Function): TemplateCmd[] {
|
componentTemplateFactory: Function): TemplateCmd[] {
|
||||||
var visitor = new CommandBuilderVisitor(
|
var visitor = new CommandBuilderVisitor(
|
||||||
new RuntimeCommandFactory(componentTemplateFactory, changeDetectorFactories), component, 0);
|
new RuntimeCommandFactory(component, appId, templateId, componentTemplateFactory,
|
||||||
|
changeDetectorFactories),
|
||||||
|
0);
|
||||||
templateVisitAll(visitor, template);
|
templateVisitAll(visitor, template);
|
||||||
return visitor.result;
|
return visitor.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileComponentCodeGen(component: CompileDirectiveMetadata, template: TemplateAst[],
|
compileComponentCodeGen(component: CompileDirectiveMetadata, appIdExpr: string,
|
||||||
|
templateIdExpr: string, template: TemplateAst[],
|
||||||
changeDetectorFactoryExpressions: string[],
|
changeDetectorFactoryExpressions: string[],
|
||||||
componentTemplateFactory: Function): SourceExpression {
|
componentTemplateFactory: Function): SourceExpression {
|
||||||
var visitor = new CommandBuilderVisitor(
|
var visitor = new CommandBuilderVisitor(
|
||||||
new CodegenCommandFactory(componentTemplateFactory, changeDetectorFactoryExpressions),
|
new CodegenCommandFactory(component, appIdExpr, templateIdExpr, componentTemplateFactory,
|
||||||
component, 0);
|
changeDetectorFactoryExpressions),
|
||||||
|
0);
|
||||||
templateVisitAll(visitor, template);
|
templateVisitAll(visitor, template);
|
||||||
var source = `[${visitor.result.join(',')}]`;
|
var source = `[${visitor.result.join(',')}]`;
|
||||||
return new SourceExpression([], source);
|
return new SourceExpression([], source);
|
||||||
|
@ -78,11 +88,27 @@ interface CommandFactory<R> {
|
||||||
}
|
}
|
||||||
|
|
||||||
class RuntimeCommandFactory implements CommandFactory<TemplateCmd> {
|
class RuntimeCommandFactory implements CommandFactory<TemplateCmd> {
|
||||||
constructor(public componentTemplateFactory: Function,
|
constructor(private component: CompileDirectiveMetadata, private appId: string,
|
||||||
public changeDetectorFactories: Function[]) {}
|
private templateId: number, private componentTemplateFactory: Function,
|
||||||
|
private changeDetectorFactories: Function[]) {}
|
||||||
private _mapDirectives(directives: CompileDirectiveMetadata[]): Type[] {
|
private _mapDirectives(directives: CompileDirectiveMetadata[]): Type[] {
|
||||||
return directives.map(directive => directive.type.runtime);
|
return directives.map(directive => directive.type.runtime);
|
||||||
}
|
}
|
||||||
|
private _addStyleShimAttributes(attrNameAndValues: string[],
|
||||||
|
localComponent: CompileDirectiveMetadata,
|
||||||
|
localTemplateId: number): string[] {
|
||||||
|
var additionalStyles = [];
|
||||||
|
if (isPresent(localComponent) &&
|
||||||
|
localComponent.template.encapsulation === ViewEncapsulation.Emulated) {
|
||||||
|
additionalStyles.push(shimHostAttribute(this.appId, localTemplateId));
|
||||||
|
additionalStyles.push('');
|
||||||
|
}
|
||||||
|
if (this.component.template.encapsulation === ViewEncapsulation.Emulated) {
|
||||||
|
additionalStyles.push(shimContentAttribute(this.appId, this.templateId));
|
||||||
|
additionalStyles.push('');
|
||||||
|
}
|
||||||
|
return additionalStyles.concat(attrNameAndValues);
|
||||||
|
}
|
||||||
|
|
||||||
createText(value: string, isBound: boolean, ngContentIndex: number): TemplateCmd {
|
createText(value: string, isBound: boolean, ngContentIndex: number): TemplateCmd {
|
||||||
return text(value, isBound, ngContentIndex);
|
return text(value, isBound, ngContentIndex);
|
||||||
|
@ -91,16 +117,19 @@ class RuntimeCommandFactory implements CommandFactory<TemplateCmd> {
|
||||||
createBeginElement(name: string, attrNameAndValues: string[], eventTargetAndNames: string[],
|
createBeginElement(name: string, attrNameAndValues: string[], eventTargetAndNames: string[],
|
||||||
variableNameAndValues: string[], directives: CompileDirectiveMetadata[],
|
variableNameAndValues: string[], directives: CompileDirectiveMetadata[],
|
||||||
isBound: boolean, ngContentIndex: number): TemplateCmd {
|
isBound: boolean, ngContentIndex: number): TemplateCmd {
|
||||||
return beginElement(name, attrNameAndValues, eventTargetAndNames, variableNameAndValues,
|
return beginElement(name, this._addStyleShimAttributes(attrNameAndValues, null, null),
|
||||||
this._mapDirectives(directives), isBound, ngContentIndex);
|
eventTargetAndNames, variableNameAndValues, this._mapDirectives(directives),
|
||||||
|
isBound, ngContentIndex);
|
||||||
}
|
}
|
||||||
createEndElement(): TemplateCmd { return endElement(); }
|
createEndElement(): TemplateCmd { return endElement(); }
|
||||||
createBeginComponent(name: string, attrNameAndValues: string[], eventTargetAndNames: string[],
|
createBeginComponent(name: string, attrNameAndValues: string[], eventTargetAndNames: string[],
|
||||||
variableNameAndValues: string[], directives: CompileDirectiveMetadata[],
|
variableNameAndValues: string[], directives: CompileDirectiveMetadata[],
|
||||||
nativeShadow: boolean, ngContentIndex: number): TemplateCmd {
|
nativeShadow: boolean, ngContentIndex: number): TemplateCmd {
|
||||||
return beginComponent(name, attrNameAndValues, eventTargetAndNames, variableNameAndValues,
|
var nestedTemplate = this.componentTemplateFactory(directives[0]);
|
||||||
this._mapDirectives(directives), nativeShadow, ngContentIndex,
|
return beginComponent(
|
||||||
this.componentTemplateFactory(directives[0]));
|
name, this._addStyleShimAttributes(attrNameAndValues, directives[0], nestedTemplate.id),
|
||||||
|
eventTargetAndNames, variableNameAndValues, this._mapDirectives(directives), nativeShadow,
|
||||||
|
ngContentIndex, nestedTemplate);
|
||||||
}
|
}
|
||||||
createEndComponent(): TemplateCmd { return endComponent(); }
|
createEndComponent(): TemplateCmd { return endComponent(); }
|
||||||
createEmbeddedTemplate(embeddedTemplateIndex: number, attrNameAndValues: string[],
|
createEmbeddedTemplate(embeddedTemplateIndex: number, attrNameAndValues: string[],
|
||||||
|
@ -113,21 +142,28 @@ class RuntimeCommandFactory implements CommandFactory<TemplateCmd> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function escapePrimitiveArray(data: any[]): string {
|
|
||||||
return `[${data.map( (value) => {
|
|
||||||
if (isString(value)) {
|
|
||||||
return escapeSingleQuoteString(value);
|
|
||||||
} else if (isBlank(value)) {
|
|
||||||
return 'null';
|
|
||||||
} else {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}).join(',')}]`;
|
|
||||||
}
|
|
||||||
|
|
||||||
class CodegenCommandFactory implements CommandFactory<string> {
|
class CodegenCommandFactory implements CommandFactory<string> {
|
||||||
constructor(public componentTemplateFactory: Function,
|
constructor(private component: CompileDirectiveMetadata, private appIdExpr: string,
|
||||||
public changeDetectorFactoryExpressions: string[]) {}
|
private templateIdExpr: string, private componentTemplateFactory: Function,
|
||||||
|
private changeDetectorFactoryExpressions: string[]) {}
|
||||||
|
|
||||||
|
private _addStyleShimAttributes(attrNameAndValues: string[],
|
||||||
|
localComponent: CompileDirectiveMetadata,
|
||||||
|
localTemplateIdExpr: string): any[] {
|
||||||
|
var additionalStlyes = [];
|
||||||
|
if (isPresent(localComponent) &&
|
||||||
|
localComponent.template.encapsulation === ViewEncapsulation.Emulated) {
|
||||||
|
additionalStlyes.push(
|
||||||
|
new Expression(shimHostAttributeExpr(this.appIdExpr, localTemplateIdExpr)));
|
||||||
|
additionalStlyes.push('');
|
||||||
|
}
|
||||||
|
if (this.component.template.encapsulation === ViewEncapsulation.Emulated) {
|
||||||
|
additionalStlyes.push(
|
||||||
|
new Expression(shimContentAttributeExpr(this.appIdExpr, this.templateIdExpr)));
|
||||||
|
additionalStlyes.push('');
|
||||||
|
}
|
||||||
|
return additionalStlyes.concat(attrNameAndValues);
|
||||||
|
}
|
||||||
|
|
||||||
createText(value: string, isBound: boolean, ngContentIndex: number): string {
|
createText(value: string, isBound: boolean, ngContentIndex: number): string {
|
||||||
return `${TEMPLATE_COMMANDS_MODULE_REF}text(${escapeSingleQuoteString(value)}, ${isBound}, ${ngContentIndex})`;
|
return `${TEMPLATE_COMMANDS_MODULE_REF}text(${escapeSingleQuoteString(value)}, ${isBound}, ${ngContentIndex})`;
|
||||||
|
@ -138,28 +174,27 @@ class CodegenCommandFactory implements CommandFactory<string> {
|
||||||
createBeginElement(name: string, attrNameAndValues: string[], eventTargetAndNames: string[],
|
createBeginElement(name: string, attrNameAndValues: string[], eventTargetAndNames: string[],
|
||||||
variableNameAndValues: string[], directives: CompileDirectiveMetadata[],
|
variableNameAndValues: string[], directives: CompileDirectiveMetadata[],
|
||||||
isBound: boolean, ngContentIndex: number): string {
|
isBound: boolean, ngContentIndex: number): string {
|
||||||
return `${TEMPLATE_COMMANDS_MODULE_REF}beginElement(${escapeSingleQuoteString(name)}, ${escapePrimitiveArray(attrNameAndValues)}, ${escapePrimitiveArray(eventTargetAndNames)}, ${escapePrimitiveArray(variableNameAndValues)}, [${_escapeDirectives(directives).join(',')}], ${isBound}, ${ngContentIndex})`;
|
var attrsExpression = codeGenArray(this._addStyleShimAttributes(attrNameAndValues, null, null));
|
||||||
|
return `${TEMPLATE_COMMANDS_MODULE_REF}beginElement(${escapeSingleQuoteString(name)}, ${attrsExpression}, ${codeGenArray(eventTargetAndNames)}, ${codeGenArray(variableNameAndValues)}, ${codeGenDirectivesArray(directives)}, ${isBound}, ${ngContentIndex})`;
|
||||||
}
|
}
|
||||||
createEndElement(): string { return `${TEMPLATE_COMMANDS_MODULE_REF}endElement()`; }
|
createEndElement(): string { return `${TEMPLATE_COMMANDS_MODULE_REF}endElement()`; }
|
||||||
createBeginComponent(name: string, attrNameAndValues: string[], eventTargetAndNames: string[],
|
createBeginComponent(name: string, attrNameAndValues: string[], eventTargetAndNames: string[],
|
||||||
variableNameAndValues: string[], directives: CompileDirectiveMetadata[],
|
variableNameAndValues: string[], directives: CompileDirectiveMetadata[],
|
||||||
nativeShadow: boolean, ngContentIndex: number): string {
|
nativeShadow: boolean, ngContentIndex: number): string {
|
||||||
return `${TEMPLATE_COMMANDS_MODULE_REF}beginComponent(${escapeSingleQuoteString(name)}, ${escapePrimitiveArray(attrNameAndValues)}, ${escapePrimitiveArray(eventTargetAndNames)}, ${escapePrimitiveArray(variableNameAndValues)}, [${_escapeDirectives(directives).join(',')}], ${nativeShadow}, ${ngContentIndex}, ${this.componentTemplateFactory(directives[0])})`;
|
var nestedCompExpr = this.componentTemplateFactory(directives[0]);
|
||||||
|
var attrsExpression = codeGenArray(
|
||||||
|
this._addStyleShimAttributes(attrNameAndValues, directives[0], `${nestedCompExpr}.id`));
|
||||||
|
return `${TEMPLATE_COMMANDS_MODULE_REF}beginComponent(${escapeSingleQuoteString(name)}, ${attrsExpression}, ${codeGenArray(eventTargetAndNames)}, ${codeGenArray(variableNameAndValues)}, ${codeGenDirectivesArray(directives)}, ${nativeShadow}, ${ngContentIndex}, ${nestedCompExpr})`;
|
||||||
}
|
}
|
||||||
createEndComponent(): string { return `${TEMPLATE_COMMANDS_MODULE_REF}endComponent()`; }
|
createEndComponent(): string { return `${TEMPLATE_COMMANDS_MODULE_REF}endComponent()`; }
|
||||||
createEmbeddedTemplate(embeddedTemplateIndex: number, attrNameAndValues: string[],
|
createEmbeddedTemplate(embeddedTemplateIndex: number, attrNameAndValues: string[],
|
||||||
variableNameAndValues: string[], directives: CompileDirectiveMetadata[],
|
variableNameAndValues: string[], directives: CompileDirectiveMetadata[],
|
||||||
isMerged: boolean, ngContentIndex: number, children: string[]): string {
|
isMerged: boolean, ngContentIndex: number, children: string[]): string {
|
||||||
return `${TEMPLATE_COMMANDS_MODULE_REF}embeddedTemplate(${escapePrimitiveArray(attrNameAndValues)}, ${escapePrimitiveArray(variableNameAndValues)}, ` +
|
return `${TEMPLATE_COMMANDS_MODULE_REF}embeddedTemplate(${codeGenArray(attrNameAndValues)}, ${codeGenArray(variableNameAndValues)}, ` +
|
||||||
`[${_escapeDirectives(directives).join(',')}], ${isMerged}, ${ngContentIndex}, ${this.changeDetectorFactoryExpressions[embeddedTemplateIndex]}, [${children.join(',')}])`;
|
`${codeGenDirectivesArray(directives)}, ${isMerged}, ${ngContentIndex}, ${this.changeDetectorFactoryExpressions[embeddedTemplateIndex]}, [${children.join(',')}])`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function _escapeDirectives(directives: CompileDirectiveMetadata[]): string[] {
|
|
||||||
return directives.map(directiveType =>
|
|
||||||
`${moduleRef(directiveType.type.moduleId)}${directiveType.type.name}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
function visitAndReturnContext(visitor: TemplateAstVisitor, asts: TemplateAst[], context: any):
|
function visitAndReturnContext(visitor: TemplateAstVisitor, asts: TemplateAst[], context: any):
|
||||||
any {
|
any {
|
||||||
templateVisitAll(visitor, asts, context);
|
templateVisitAll(visitor, asts, context);
|
||||||
|
@ -169,22 +204,11 @@ function visitAndReturnContext(visitor: TemplateAstVisitor, asts: TemplateAst[],
|
||||||
class CommandBuilderVisitor<R> implements TemplateAstVisitor {
|
class CommandBuilderVisitor<R> implements TemplateAstVisitor {
|
||||||
result: R[] = [];
|
result: R[] = [];
|
||||||
transitiveNgContentCount: number = 0;
|
transitiveNgContentCount: number = 0;
|
||||||
constructor(public commandFactory: CommandFactory<R>, public component: CompileDirectiveMetadata,
|
constructor(public commandFactory: CommandFactory<R>, public embeddedTemplateIndex: number) {}
|
||||||
public embeddedTemplateIndex: number) {}
|
|
||||||
|
|
||||||
private _readAttrNameAndValues(localComponent: CompileDirectiveMetadata,
|
private _readAttrNameAndValues(directives: CompileDirectiveMetadata[],
|
||||||
directives: CompileDirectiveMetadata[],
|
|
||||||
attrAsts: TemplateAst[]): string[] {
|
attrAsts: TemplateAst[]): string[] {
|
||||||
var attrNameAndValues: string[] = visitAndReturnContext(this, attrAsts, []);
|
var attrNameAndValues: string[] = visitAndReturnContext(this, attrAsts, []);
|
||||||
if (isPresent(localComponent) &&
|
|
||||||
localComponent.template.encapsulation === ViewEncapsulation.Emulated) {
|
|
||||||
attrNameAndValues.push(shimHostAttribute(localComponent.type.id));
|
|
||||||
attrNameAndValues.push('');
|
|
||||||
}
|
|
||||||
if (this.component.template.encapsulation === ViewEncapsulation.Emulated) {
|
|
||||||
attrNameAndValues.push(shimContentAttribute(this.component.type.id));
|
|
||||||
attrNameAndValues.push('');
|
|
||||||
}
|
|
||||||
directives.forEach(directiveMeta => {
|
directives.forEach(directiveMeta => {
|
||||||
StringMapWrapper.forEach(directiveMeta.hostAttributes, (value, name) => {
|
StringMapWrapper.forEach(directiveMeta.hostAttributes, (value, name) => {
|
||||||
attrNameAndValues.push(name);
|
attrNameAndValues.push(name);
|
||||||
|
@ -201,8 +225,7 @@ class CommandBuilderVisitor<R> implements TemplateAstVisitor {
|
||||||
}
|
}
|
||||||
visitEmbeddedTemplate(ast: EmbeddedTemplateAst, context: any): any {
|
visitEmbeddedTemplate(ast: EmbeddedTemplateAst, context: any): any {
|
||||||
this.embeddedTemplateIndex++;
|
this.embeddedTemplateIndex++;
|
||||||
var childVisitor =
|
var childVisitor = new CommandBuilderVisitor(this.commandFactory, this.embeddedTemplateIndex);
|
||||||
new CommandBuilderVisitor(this.commandFactory, this.component, this.embeddedTemplateIndex);
|
|
||||||
templateVisitAll(childVisitor, ast.children);
|
templateVisitAll(childVisitor, ast.children);
|
||||||
var isMerged = childVisitor.transitiveNgContentCount > 0;
|
var isMerged = childVisitor.transitiveNgContentCount > 0;
|
||||||
var variableNameAndValues = [];
|
var variableNameAndValues = [];
|
||||||
|
@ -215,7 +238,7 @@ class CommandBuilderVisitor<R> implements TemplateAstVisitor {
|
||||||
directiveAst.visit(this, new DirectiveContext(index, [], [], directives));
|
directiveAst.visit(this, new DirectiveContext(index, [], [], directives));
|
||||||
});
|
});
|
||||||
this.result.push(this.commandFactory.createEmbeddedTemplate(
|
this.result.push(this.commandFactory.createEmbeddedTemplate(
|
||||||
this.embeddedTemplateIndex, this._readAttrNameAndValues(null, directives, ast.attrs),
|
this.embeddedTemplateIndex, this._readAttrNameAndValues(directives, ast.attrs),
|
||||||
variableNameAndValues, directives, isMerged, ast.ngContentIndex, childVisitor.result));
|
variableNameAndValues, directives, isMerged, ast.ngContentIndex, childVisitor.result));
|
||||||
this.transitiveNgContentCount += childVisitor.transitiveNgContentCount;
|
this.transitiveNgContentCount += childVisitor.transitiveNgContentCount;
|
||||||
this.embeddedTemplateIndex = childVisitor.embeddedTemplateIndex;
|
this.embeddedTemplateIndex = childVisitor.embeddedTemplateIndex;
|
||||||
|
@ -238,7 +261,7 @@ class CommandBuilderVisitor<R> implements TemplateAstVisitor {
|
||||||
});
|
});
|
||||||
eventTargetAndNames = removeKeyValueArrayDuplicates(eventTargetAndNames);
|
eventTargetAndNames = removeKeyValueArrayDuplicates(eventTargetAndNames);
|
||||||
|
|
||||||
var attrNameAndValues = this._readAttrNameAndValues(component, directives, ast.attrs);
|
var attrNameAndValues = this._readAttrNameAndValues(directives, ast.attrs);
|
||||||
if (isPresent(component)) {
|
if (isPresent(component)) {
|
||||||
this.result.push(this.commandFactory.createBeginComponent(
|
this.result.push(this.commandFactory.createBeginComponent(
|
||||||
ast.name, attrNameAndValues, eventTargetAndNames, variableNameAndValues, directives,
|
ast.name, attrNameAndValues, eventTargetAndNames, variableNameAndValues, directives,
|
||||||
|
@ -306,4 +329,30 @@ class DirectiveContext {
|
||||||
constructor(public index: number, public eventTargetAndNames: string[],
|
constructor(public index: number, public eventTargetAndNames: string[],
|
||||||
public targetVariableNameAndValues: any[],
|
public targetVariableNameAndValues: any[],
|
||||||
public targetDirectives: CompileDirectiveMetadata[]) {}
|
public targetDirectives: CompileDirectiveMetadata[]) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Expression {
|
||||||
|
constructor(public value: string) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
function escapeValue(value: any): string {
|
||||||
|
if (value instanceof Expression) {
|
||||||
|
return value.value;
|
||||||
|
} else if (isString(value)) {
|
||||||
|
return escapeSingleQuoteString(value);
|
||||||
|
} else if (isBlank(value)) {
|
||||||
|
return 'null';
|
||||||
|
} else {
|
||||||
|
return `${value}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function codeGenArray(data: any[]): string {
|
||||||
|
return `[${data.map(escapeValue).join(',')}]`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function codeGenDirectivesArray(directives: CompileDirectiveMetadata[]): string {
|
||||||
|
var expressions = directives.map(
|
||||||
|
directiveType => `${moduleRef(directiveType.type.moduleId)}${directiveType.type.name}`);
|
||||||
|
return `[${expressions.join(',')}]`;
|
||||||
|
}
|
||||||
|
|
|
@ -22,27 +22,22 @@ import {LifecycleHooks, LIFECYCLE_HOOKS_VALUES} from 'angular2/src/core/compiler
|
||||||
var HOST_REG_EXP = /^(?:(?:\[([^\]]+)\])|(?:\(([^\)]+)\)))$/g;
|
var HOST_REG_EXP = /^(?:(?:\[([^\]]+)\])|(?:\(([^\)]+)\)))$/g;
|
||||||
|
|
||||||
export class CompileTypeMetadata {
|
export class CompileTypeMetadata {
|
||||||
id: number;
|
|
||||||
runtime: Type;
|
runtime: Type;
|
||||||
name: string;
|
name: string;
|
||||||
moduleId: string;
|
moduleId: string;
|
||||||
constructor({id, runtime, name, moduleId}:
|
constructor({runtime, name, moduleId}: {runtime?: Type, name?: string, moduleId?: string} = {}) {
|
||||||
{id?: number, runtime?: Type, name?: string, moduleId?: string} = {}) {
|
|
||||||
this.id = id;
|
|
||||||
this.runtime = runtime;
|
this.runtime = runtime;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.moduleId = moduleId;
|
this.moduleId = moduleId;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(data: StringMap<string, any>): CompileTypeMetadata {
|
static fromJson(data: StringMap<string, any>): CompileTypeMetadata {
|
||||||
return new CompileTypeMetadata(
|
return new CompileTypeMetadata({name: data['name'], moduleId: data['moduleId']});
|
||||||
{id: data['id'], name: data['name'], moduleId: data['moduleId']});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
toJson(): StringMap<string, any> {
|
toJson(): StringMap<string, any> {
|
||||||
return {
|
return {
|
||||||
// Note: Runtime type can't be serialized...
|
// Note: Runtime type can't be serialized...
|
||||||
'id': this.id,
|
|
||||||
'name': this.name,
|
'name': this.name,
|
||||||
'moduleId': this.moduleId
|
'moduleId': this.moduleId
|
||||||
};
|
};
|
||||||
|
@ -253,12 +248,8 @@ export function createHostComponentMeta(componentType: CompileTypeMetadata,
|
||||||
componentSelector: string): CompileDirectiveMetadata {
|
componentSelector: string): CompileDirectiveMetadata {
|
||||||
var template = CssSelector.parse(componentSelector)[0].getMatchingElementTemplate();
|
var template = CssSelector.parse(componentSelector)[0].getMatchingElementTemplate();
|
||||||
return CompileDirectiveMetadata.create({
|
return CompileDirectiveMetadata.create({
|
||||||
type: new CompileTypeMetadata({
|
type: new CompileTypeMetadata(
|
||||||
runtime: Object,
|
{runtime: Object, name: `Host${componentType.name}`, moduleId: componentType.moduleId}),
|
||||||
id: (componentType.id * -1) - 1,
|
|
||||||
name: `Host${componentType.name}`,
|
|
||||||
moduleId: componentType.moduleId
|
|
||||||
}),
|
|
||||||
template: new CompileTemplateMetadata(
|
template: new CompileTemplateMetadata(
|
||||||
{template: template, templateUrl: '', styles: [], styleUrls: [], ngContentSelectors: []}),
|
{template: template, templateUrl: '', styles: [], styleUrls: [], ngContentSelectors: []}),
|
||||||
changeDetection: ChangeDetectionStrategy.Default,
|
changeDetection: ChangeDetectionStrategy.Default,
|
||||||
|
|
|
@ -25,7 +25,6 @@ var HOST_REG_EXP = /^(?:(?:\[([^\]]+)\])|(?:\(([^\)]+)\)))$/g;
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class RuntimeMetadataResolver {
|
export class RuntimeMetadataResolver {
|
||||||
private _directiveCounter = 0;
|
|
||||||
private _cache: Map<Type, cpl.CompileDirectiveMetadata> = new Map();
|
private _cache: Map<Type, cpl.CompileDirectiveMetadata> = new Map();
|
||||||
|
|
||||||
constructor(private _directiveResolver: DirectiveResolver, private _viewResolver: ViewResolver) {}
|
constructor(private _directiveResolver: DirectiveResolver, private _viewResolver: ViewResolver) {}
|
||||||
|
@ -55,12 +54,8 @@ export class RuntimeMetadataResolver {
|
||||||
exportAs: directiveAnnotation.exportAs,
|
exportAs: directiveAnnotation.exportAs,
|
||||||
isComponent: isPresent(templateMeta),
|
isComponent: isPresent(templateMeta),
|
||||||
dynamicLoadable: true,
|
dynamicLoadable: true,
|
||||||
type: new cpl.CompileTypeMetadata({
|
type: new cpl.CompileTypeMetadata(
|
||||||
id: this._directiveCounter++,
|
{name: stringify(directiveType), moduleId: moduleId, runtime: directiveType}),
|
||||||
name: stringify(directiveType),
|
|
||||||
moduleId: moduleId,
|
|
||||||
runtime: directiveType
|
|
||||||
}),
|
|
||||||
template: templateMeta,
|
template: templateMeta,
|
||||||
changeDetection: changeDetectionStrategy,
|
changeDetection: changeDetectionStrategy,
|
||||||
properties: directiveAnnotation.properties,
|
properties: directiveAnnotation.properties,
|
||||||
|
@ -89,8 +84,8 @@ export class RuntimeMetadataResolver {
|
||||||
|
|
||||||
function removeDuplicatedDirectives(directives: cpl.CompileDirectiveMetadata[]):
|
function removeDuplicatedDirectives(directives: cpl.CompileDirectiveMetadata[]):
|
||||||
cpl.CompileDirectiveMetadata[] {
|
cpl.CompileDirectiveMetadata[] {
|
||||||
var directivesMap: Map<number, cpl.CompileDirectiveMetadata> = new Map();
|
var directivesMap: Map<Type, cpl.CompileDirectiveMetadata> = new Map();
|
||||||
directives.forEach((dirMeta) => { directivesMap.set(dirMeta.type.id, dirMeta); });
|
directives.forEach((dirMeta) => { directivesMap.set(dirMeta.type.runtime, dirMeta); });
|
||||||
return MapWrapper.values(directivesMap);
|
return MapWrapper.values(directivesMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,14 +13,17 @@ import {
|
||||||
codeGenConcatArray,
|
codeGenConcatArray,
|
||||||
codeGenMapArray,
|
codeGenMapArray,
|
||||||
codeGenReplaceAll,
|
codeGenReplaceAll,
|
||||||
codeGenExportVariable
|
codeGenExportVariable,
|
||||||
|
codeGenToString
|
||||||
} from './util';
|
} from './util';
|
||||||
import {Injectable} from 'angular2/src/core/di';
|
import {Injectable} from 'angular2/src/core/di';
|
||||||
|
|
||||||
const COMPONENT_VARIABLE = '%COMP%';
|
const COMPONENT_VARIABLE = '%COMP%';
|
||||||
var COMPONENT_REGEX = /%COMP%/g;
|
var COMPONENT_REGEX = /%COMP%/g;
|
||||||
const HOST_ATTR = `_nghost-${COMPONENT_VARIABLE}`;
|
const HOST_ATTR = `_nghost-${COMPONENT_VARIABLE}`;
|
||||||
|
const HOST_ATTR_EXPR = `'_nghost-'+${COMPONENT_VARIABLE}`;
|
||||||
const CONTENT_ATTR = `_ngcontent-${COMPONENT_VARIABLE}`;
|
const CONTENT_ATTR = `_ngcontent-${COMPONENT_VARIABLE}`;
|
||||||
|
const CONTENT_ATTR_EXPR = `'_ngcontent-'+${COMPONENT_VARIABLE}`;
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class StyleCompiler {
|
export class StyleCompiler {
|
||||||
|
@ -29,24 +32,24 @@ export class StyleCompiler {
|
||||||
|
|
||||||
constructor(private _xhr: XHR, private _urlResolver: UrlResolver) {}
|
constructor(private _xhr: XHR, private _urlResolver: UrlResolver) {}
|
||||||
|
|
||||||
compileComponentRuntime(type: CompileTypeMetadata,
|
compileComponentRuntime(appId: string, templateId: number,
|
||||||
template: CompileTemplateMetadata): Promise<string[]> {
|
template: CompileTemplateMetadata): Promise<string[]> {
|
||||||
var styles = template.styles;
|
var styles = template.styles;
|
||||||
var styleAbsUrls = template.styleUrls;
|
var styleAbsUrls = template.styleUrls;
|
||||||
return this._loadStyles(styles, styleAbsUrls,
|
return this._loadStyles(styles, styleAbsUrls,
|
||||||
template.encapsulation === ViewEncapsulation.Emulated)
|
template.encapsulation === ViewEncapsulation.Emulated)
|
||||||
.then(styles => styles.map(
|
.then(styles => styles.map(style => StringWrapper.replaceAll(
|
||||||
style => StringWrapper.replaceAll(style, COMPONENT_REGEX, `${type.id}`)));
|
style, COMPONENT_REGEX, componentId(appId, templateId))));
|
||||||
}
|
}
|
||||||
|
|
||||||
compileComponentCodeGen(type: CompileTypeMetadata,
|
compileComponentCodeGen(appIdExpression: string, templateIdExpression: string,
|
||||||
template: CompileTemplateMetadata): SourceExpression {
|
template: CompileTemplateMetadata): SourceExpression {
|
||||||
var shim = template.encapsulation === ViewEncapsulation.Emulated;
|
var shim = template.encapsulation === ViewEncapsulation.Emulated;
|
||||||
var suffix;
|
var suffix;
|
||||||
if (shim) {
|
if (shim) {
|
||||||
var componentId = `${ type.id}`;
|
suffix = codeGenMapArray(
|
||||||
suffix =
|
['style'],
|
||||||
codeGenMapArray(['style'], `style${codeGenReplaceAll(COMPONENT_VARIABLE, componentId)}`);
|
`style${codeGenReplaceAll(COMPONENT_VARIABLE, componentIdExpression(appIdExpression, templateIdExpression))}`);
|
||||||
} else {
|
} else {
|
||||||
suffix = '';
|
suffix = '';
|
||||||
}
|
}
|
||||||
|
@ -118,10 +121,28 @@ export class StyleCompiler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function shimContentAttribute(componentId: number): string {
|
export function shimContentAttribute(appId: string, templateId: number): string {
|
||||||
return StringWrapper.replaceAll(CONTENT_ATTR, COMPONENT_REGEX, `${componentId}`);
|
return StringWrapper.replaceAll(CONTENT_ATTR, COMPONENT_REGEX, componentId(appId, templateId));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function shimHostAttribute(componentId: number): string {
|
export function shimContentAttributeExpr(appIdExpr: string, templateIdExpr: string): string {
|
||||||
return StringWrapper.replaceAll(HOST_ATTR, COMPONENT_REGEX, `${componentId}`);
|
return StringWrapper.replaceAll(CONTENT_ATTR_EXPR, COMPONENT_REGEX,
|
||||||
|
componentIdExpression(appIdExpr, templateIdExpr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function shimHostAttribute(appId: string, templateId: number): string {
|
||||||
|
return StringWrapper.replaceAll(HOST_ATTR, COMPONENT_REGEX, componentId(appId, templateId));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function shimHostAttributeExpr(appIdExpr: string, templateIdExpr: string): string {
|
||||||
|
return StringWrapper.replaceAll(HOST_ATTR_EXPR, COMPONENT_REGEX,
|
||||||
|
componentIdExpression(appIdExpr, templateIdExpr));
|
||||||
|
}
|
||||||
|
|
||||||
|
function componentId(appId: string, templateId: number): string {
|
||||||
|
return `${appId}-${templateId}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function componentIdExpression(appIdExpression: string, templateIdExpression: string): string {
|
||||||
|
return `${appIdExpression}+'-'+${codeGenToString(templateIdExpression)}`;
|
||||||
|
}
|
|
@ -2,7 +2,12 @@ import {Type, Json, isBlank, stringify} from 'angular2/src/core/facade/lang';
|
||||||
import {BaseException} from 'angular2/src/core/facade/exceptions';
|
import {BaseException} from 'angular2/src/core/facade/exceptions';
|
||||||
import {ListWrapper, SetWrapper} from 'angular2/src/core/facade/collection';
|
import {ListWrapper, SetWrapper} from 'angular2/src/core/facade/collection';
|
||||||
import {PromiseWrapper, Promise} from 'angular2/src/core/facade/async';
|
import {PromiseWrapper, Promise} from 'angular2/src/core/facade/async';
|
||||||
import {CompiledTemplate, TemplateCmd} from 'angular2/src/core/compiler/template_commands';
|
import {
|
||||||
|
CompiledTemplate,
|
||||||
|
TemplateCmd,
|
||||||
|
nextTemplateId,
|
||||||
|
CompiledHostTemplate
|
||||||
|
} from 'angular2/src/core/compiler/template_commands';
|
||||||
import {
|
import {
|
||||||
createHostComponentMeta,
|
createHostComponentMeta,
|
||||||
CompileDirectiveMetadata,
|
CompileDirectiveMetadata,
|
||||||
|
@ -18,20 +23,26 @@ import {CommandCompiler} from './command_compiler';
|
||||||
import {TemplateParser} from './template_parser';
|
import {TemplateParser} from './template_parser';
|
||||||
import {TemplateNormalizer} from './template_normalizer';
|
import {TemplateNormalizer} from './template_normalizer';
|
||||||
import {RuntimeMetadataResolver} from './runtime_metadata';
|
import {RuntimeMetadataResolver} from './runtime_metadata';
|
||||||
|
import {APP_ID} from 'angular2/src/core/render/dom/dom_tokens';
|
||||||
|
|
||||||
import {TEMPLATE_COMMANDS_MODULE_REF} from './command_compiler';
|
import {TEMPLATE_COMMANDS_MODULE_REF} from './command_compiler';
|
||||||
import {IS_DART, codeGenExportVariable, escapeSingleQuoteString, codeGenValueFn} from './util';
|
import {IS_DART, codeGenExportVariable, escapeSingleQuoteString, codeGenValueFn} from './util';
|
||||||
|
import {Inject} from 'angular2/src/core/di';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class TemplateCompiler {
|
export class TemplateCompiler {
|
||||||
private _compiledTemplateCache: Map<number, CompiledTemplate> = new Map();
|
private _hostCacheKeys: Map<Type, any> = new Map();
|
||||||
private _compiledTemplateDone: Map<number, Promise<CompiledTemplate>> = new Map();
|
private _compiledTemplateCache: Map<Type, CompiledTemplate> = new Map();
|
||||||
|
private _compiledTemplateDone: Map<Type, Promise<CompiledTemplate>> = new Map();
|
||||||
|
private _appId: string;
|
||||||
|
|
||||||
constructor(private _runtimeMetadataResolver: RuntimeMetadataResolver,
|
constructor(private _runtimeMetadataResolver: RuntimeMetadataResolver,
|
||||||
private _templateNormalizer: TemplateNormalizer,
|
private _templateNormalizer: TemplateNormalizer,
|
||||||
private _templateParser: TemplateParser, private _styleCompiler: StyleCompiler,
|
private _templateParser: TemplateParser, private _styleCompiler: StyleCompiler,
|
||||||
private _commandCompiler: CommandCompiler,
|
private _commandCompiler: CommandCompiler,
|
||||||
private _cdCompiler: ChangeDetectionCompiler) {}
|
private _cdCompiler: ChangeDetectionCompiler, @Inject(APP_ID) appId: string) {
|
||||||
|
this._appId = appId;
|
||||||
|
}
|
||||||
|
|
||||||
normalizeDirectiveMetadata(directive:
|
normalizeDirectiveMetadata(directive:
|
||||||
CompileDirectiveMetadata): Promise<CompileDirectiveMetadata> {
|
CompileDirectiveMetadata): Promise<CompileDirectiveMetadata> {
|
||||||
|
@ -63,40 +74,49 @@ export class TemplateCompiler {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
compileHostComponentRuntime(type: Type): Promise<CompiledTemplate> {
|
compileHostComponentRuntime(type: Type): Promise<CompiledHostTemplate> {
|
||||||
var compMeta: CompileDirectiveMetadata = this._runtimeMetadataResolver.getMetadata(type);
|
var hostCacheKey = this._hostCacheKeys.get(type);
|
||||||
assertComponent(compMeta);
|
if (isBlank(hostCacheKey)) {
|
||||||
var hostMeta: CompileDirectiveMetadata =
|
hostCacheKey = new Object();
|
||||||
createHostComponentMeta(compMeta.type, compMeta.selector);
|
this._hostCacheKeys.set(type, hostCacheKey);
|
||||||
|
var compMeta: CompileDirectiveMetadata = this._runtimeMetadataResolver.getMetadata(type);
|
||||||
|
assertComponent(compMeta);
|
||||||
|
var hostMeta: CompileDirectiveMetadata =
|
||||||
|
createHostComponentMeta(compMeta.type, compMeta.selector);
|
||||||
|
|
||||||
this._compileComponentRuntime(hostMeta, [compMeta], new Set());
|
this._compileComponentRuntime(hostCacheKey, hostMeta, [compMeta], new Set());
|
||||||
return this._compiledTemplateDone.get(hostMeta.type.id);
|
}
|
||||||
|
return this._compiledTemplateDone.get(hostCacheKey)
|
||||||
|
.then(compiledTemplate => new CompiledHostTemplate(() => compiledTemplate));
|
||||||
}
|
}
|
||||||
|
|
||||||
clearCache() {
|
clearCache() {
|
||||||
|
this._hostCacheKeys.clear();
|
||||||
this._styleCompiler.clearCache();
|
this._styleCompiler.clearCache();
|
||||||
this._compiledTemplateCache.clear();
|
this._compiledTemplateCache.clear();
|
||||||
this._compiledTemplateDone.clear();
|
this._compiledTemplateDone.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private _compileComponentRuntime(compMeta: CompileDirectiveMetadata,
|
private _compileComponentRuntime(cacheKey: any, compMeta: CompileDirectiveMetadata,
|
||||||
viewDirectives: CompileDirectiveMetadata[],
|
viewDirectives: CompileDirectiveMetadata[],
|
||||||
compilingComponentIds: Set<number>): CompiledTemplate {
|
compilingComponentCacheKeys: Set<any>): CompiledTemplate {
|
||||||
var compiledTemplate = this._compiledTemplateCache.get(compMeta.type.id);
|
var compiledTemplate = this._compiledTemplateCache.get(cacheKey);
|
||||||
var done = this._compiledTemplateDone.get(compMeta.type.id);
|
var done = this._compiledTemplateDone.get(cacheKey);
|
||||||
if (isBlank(compiledTemplate)) {
|
if (isBlank(compiledTemplate)) {
|
||||||
var styles;
|
var styles;
|
||||||
var changeDetectorFactory;
|
var changeDetectorFactory;
|
||||||
var commands;
|
var commands;
|
||||||
|
var templateId = nextTemplateId();
|
||||||
compiledTemplate =
|
compiledTemplate =
|
||||||
new CompiledTemplate(compMeta.type.id, () => [changeDetectorFactory, commands, styles]);
|
new CompiledTemplate(templateId, (_a, _b) => [changeDetectorFactory, commands, styles]);
|
||||||
this._compiledTemplateCache.set(compMeta.type.id, compiledTemplate);
|
this._compiledTemplateCache.set(cacheKey, compiledTemplate);
|
||||||
compilingComponentIds.add(compMeta.type.id);
|
compilingComponentCacheKeys.add(cacheKey);
|
||||||
done =
|
done =
|
||||||
PromiseWrapper
|
PromiseWrapper.all([
|
||||||
.all([
|
<any>this._styleCompiler.compileComponentRuntime(this._appId, templateId,
|
||||||
<any>this._styleCompiler.compileComponentRuntime(compMeta.type, compMeta.template)
|
compMeta.template)
|
||||||
].concat(viewDirectives.map(dirMeta => this.normalizeDirectiveMetadata(dirMeta))))
|
].concat(viewDirectives.map(dirMeta =>
|
||||||
|
this.normalizeDirectiveMetadata(dirMeta))))
|
||||||
.then((stylesAndNormalizedViewDirMetas: any[]) => {
|
.then((stylesAndNormalizedViewDirMetas: any[]) => {
|
||||||
var childPromises = [];
|
var childPromises = [];
|
||||||
var normalizedViewDirMetas = stylesAndNormalizedViewDirMetas.slice(1);
|
var normalizedViewDirMetas = stylesAndNormalizedViewDirMetas.slice(1);
|
||||||
|
@ -107,36 +127,38 @@ export class TemplateCompiler {
|
||||||
compMeta.type, compMeta.changeDetection, parsedTemplate);
|
compMeta.type, compMeta.changeDetection, parsedTemplate);
|
||||||
changeDetectorFactory = changeDetectorFactories[0];
|
changeDetectorFactory = changeDetectorFactories[0];
|
||||||
styles = stylesAndNormalizedViewDirMetas[0];
|
styles = stylesAndNormalizedViewDirMetas[0];
|
||||||
commands =
|
commands = this._compileCommandsRuntime(compMeta, templateId, parsedTemplate,
|
||||||
this._compileCommandsRuntime(compMeta, parsedTemplate, changeDetectorFactories,
|
changeDetectorFactories,
|
||||||
compilingComponentIds, childPromises);
|
compilingComponentCacheKeys, childPromises);
|
||||||
return PromiseWrapper.all(childPromises);
|
return PromiseWrapper.all(childPromises);
|
||||||
})
|
})
|
||||||
.then((_) => {
|
.then((_) => {
|
||||||
SetWrapper.delete(compilingComponentIds, compMeta.type.id);
|
SetWrapper.delete(compilingComponentCacheKeys, cacheKey);
|
||||||
return compiledTemplate;
|
return compiledTemplate;
|
||||||
});
|
});
|
||||||
this._compiledTemplateDone.set(compMeta.type.id, done);
|
this._compiledTemplateDone.set(cacheKey, done);
|
||||||
}
|
}
|
||||||
return compiledTemplate;
|
return compiledTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _compileCommandsRuntime(compMeta: CompileDirectiveMetadata, parsedTemplate: TemplateAst[],
|
private _compileCommandsRuntime(compMeta: CompileDirectiveMetadata, templateId: number,
|
||||||
|
parsedTemplate: TemplateAst[],
|
||||||
changeDetectorFactories: Function[],
|
changeDetectorFactories: Function[],
|
||||||
compilingComponentIds: Set<number>,
|
compilingComponentCacheKeys: Set<Type>,
|
||||||
childPromises: Promise<any>[]): TemplateCmd[] {
|
childPromises: Promise<any>[]): TemplateCmd[] {
|
||||||
return this._commandCompiler.compileComponentRuntime(
|
return this._commandCompiler.compileComponentRuntime(
|
||||||
compMeta, parsedTemplate, changeDetectorFactories,
|
compMeta, this._appId, templateId, parsedTemplate, changeDetectorFactories,
|
||||||
(childComponentDir: CompileDirectiveMetadata) => {
|
(childComponentDir: CompileDirectiveMetadata) => {
|
||||||
|
var childCacheKey = childComponentDir.type.runtime;
|
||||||
var childViewDirectives: CompileDirectiveMetadata[] =
|
var childViewDirectives: CompileDirectiveMetadata[] =
|
||||||
this._runtimeMetadataResolver.getViewDirectivesMetadata(
|
this._runtimeMetadataResolver.getViewDirectivesMetadata(
|
||||||
childComponentDir.type.runtime);
|
childComponentDir.type.runtime);
|
||||||
var childIsRecursive = SetWrapper.has(compilingComponentIds, childComponentDir.type.id);
|
var childIsRecursive = SetWrapper.has(compilingComponentCacheKeys, childCacheKey);
|
||||||
var childTemplate = this._compileComponentRuntime(childComponentDir, childViewDirectives,
|
var childTemplate = this._compileComponentRuntime(
|
||||||
compilingComponentIds);
|
childCacheKey, childComponentDir, childViewDirectives, compilingComponentCacheKeys);
|
||||||
if (!childIsRecursive) {
|
if (!childIsRecursive) {
|
||||||
// Only wait for a child if it is not a cycle
|
// Only wait for a child if it is not a cycle
|
||||||
childPromises.push(this._compiledTemplateDone.get(childComponentDir.type.id));
|
childPromises.push(this._compiledTemplateDone.get(childCacheKey));
|
||||||
}
|
}
|
||||||
return childTemplate;
|
return childTemplate;
|
||||||
});
|
});
|
||||||
|
@ -147,24 +169,40 @@ export class TemplateCompiler {
|
||||||
var declarations = [];
|
var declarations = [];
|
||||||
var templateArguments = [];
|
var templateArguments = [];
|
||||||
var componentMetas: CompileDirectiveMetadata[] = [];
|
var componentMetas: CompileDirectiveMetadata[] = [];
|
||||||
|
var isHost: boolean[] = [];
|
||||||
|
var templateIdVariable = 'templateId';
|
||||||
|
var appIdVariable = 'appId';
|
||||||
components.forEach(componentWithDirs => {
|
components.forEach(componentWithDirs => {
|
||||||
var compMeta = <CompileDirectiveMetadata>componentWithDirs.component;
|
var compMeta = <CompileDirectiveMetadata>componentWithDirs.component;
|
||||||
assertComponent(compMeta);
|
assertComponent(compMeta);
|
||||||
componentMetas.push(compMeta);
|
componentMetas.push(compMeta);
|
||||||
this._processTemplateCodeGen(compMeta,
|
isHost.push(false);
|
||||||
|
this._processTemplateCodeGen(compMeta, appIdVariable, templateIdVariable,
|
||||||
<CompileDirectiveMetadata[]>componentWithDirs.directives,
|
<CompileDirectiveMetadata[]>componentWithDirs.directives,
|
||||||
declarations, templateArguments);
|
declarations, templateArguments);
|
||||||
if (compMeta.dynamicLoadable) {
|
if (compMeta.dynamicLoadable) {
|
||||||
var hostMeta = createHostComponentMeta(compMeta.type, compMeta.selector);
|
var hostMeta = createHostComponentMeta(compMeta.type, compMeta.selector);
|
||||||
componentMetas.push(hostMeta);
|
componentMetas.push(hostMeta);
|
||||||
this._processTemplateCodeGen(hostMeta, [compMeta], declarations, templateArguments);
|
isHost.push(true);
|
||||||
|
this._processTemplateCodeGen(hostMeta, appIdVariable, templateIdVariable, [compMeta],
|
||||||
|
declarations, templateArguments);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
ListWrapper.forEachWithIndex(componentMetas, (compMeta: CompileDirectiveMetadata,
|
ListWrapper.forEachWithIndex(componentMetas, (compMeta: CompileDirectiveMetadata,
|
||||||
index: number) => {
|
index: number) => {
|
||||||
var templateDataFn = codeGenValueFn([], `[${(<any[]>templateArguments[index]).join(',')}]`);
|
var templateDataFn = codeGenValueFn([templateIdVariable, appIdVariable],
|
||||||
|
`[${(<any[]>templateArguments[index]).join(',')}]`);
|
||||||
|
var compiledTemplateExpr =
|
||||||
|
`new ${TEMPLATE_COMMANDS_MODULE_REF}CompiledTemplate(${TEMPLATE_COMMANDS_MODULE_REF}nextTemplateId(),${templateDataFn})`;
|
||||||
|
var variableValueExpr;
|
||||||
|
if (isHost[index]) {
|
||||||
|
variableValueExpr =
|
||||||
|
`new ${TEMPLATE_COMMANDS_MODULE_REF}CompiledHostTemplate(${codeGenValueFn([], compiledTemplateExpr)})`;
|
||||||
|
} else {
|
||||||
|
variableValueExpr = compiledTemplateExpr;
|
||||||
|
}
|
||||||
declarations.push(
|
declarations.push(
|
||||||
`${codeGenExportVariable(templateVariableName(compMeta.type))}new ${TEMPLATE_COMMANDS_MODULE_REF}CompiledTemplate(${compMeta.type.id},${templateDataFn});`);
|
`${codeGenExportVariable(templateVariableName(compMeta.type))}${variableValueExpr};`);
|
||||||
});
|
});
|
||||||
return new SourceModule(`${templateModuleName(moduleId)}`, declarations.join('\n'));
|
return new SourceModule(`${templateModuleName(moduleId)}`, declarations.join('\n'));
|
||||||
}
|
}
|
||||||
|
@ -173,16 +211,17 @@ export class TemplateCompiler {
|
||||||
return this._styleCompiler.compileStylesheetCodeGen(moduleId, cssText);
|
return this._styleCompiler.compileStylesheetCodeGen(moduleId, cssText);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _processTemplateCodeGen(compMeta: CompileDirectiveMetadata,
|
private _processTemplateCodeGen(compMeta: CompileDirectiveMetadata, appIdExpr: string,
|
||||||
directives: CompileDirectiveMetadata[],
|
templateIdExpr: string, directives: CompileDirectiveMetadata[],
|
||||||
targetDeclarations: string[], targetTemplateArguments: any[][]) {
|
targetDeclarations: string[], targetTemplateArguments: any[][]) {
|
||||||
var styleExpr = this._styleCompiler.compileComponentCodeGen(compMeta.type, compMeta.template);
|
var styleExpr =
|
||||||
|
this._styleCompiler.compileComponentCodeGen(appIdExpr, templateIdExpr, compMeta.template);
|
||||||
var parsedTemplate =
|
var parsedTemplate =
|
||||||
this._templateParser.parse(compMeta.template.template, directives, compMeta.type.name);
|
this._templateParser.parse(compMeta.template.template, directives, compMeta.type.name);
|
||||||
var changeDetectorsExprs = this._cdCompiler.compileComponentCodeGen(
|
var changeDetectorsExprs = this._cdCompiler.compileComponentCodeGen(
|
||||||
compMeta.type, compMeta.changeDetection, parsedTemplate);
|
compMeta.type, compMeta.changeDetection, parsedTemplate);
|
||||||
var commandsExpr = this._commandCompiler.compileComponentCodeGen(
|
var commandsExpr = this._commandCompiler.compileComponentCodeGen(
|
||||||
compMeta, parsedTemplate, changeDetectorsExprs.expressions,
|
compMeta, appIdExpr, templateIdExpr, parsedTemplate, changeDetectorsExprs.expressions,
|
||||||
codeGenComponentTemplateFactory);
|
codeGenComponentTemplateFactory);
|
||||||
|
|
||||||
addAll(styleExpr.declarations, targetDeclarations);
|
addAll(styleExpr.declarations, targetDeclarations);
|
||||||
|
|
|
@ -95,7 +95,7 @@ export class TemplateParser {
|
||||||
class TemplateParseVisitor implements HtmlAstVisitor {
|
class TemplateParseVisitor implements HtmlAstVisitor {
|
||||||
selectorMatcher: SelectorMatcher;
|
selectorMatcher: SelectorMatcher;
|
||||||
errors: string[] = [];
|
errors: string[] = [];
|
||||||
directivesIndexByTypeId: Map<number, number> = new Map();
|
directivesIndex: Map<CompileDirectiveMetadata, number> = new Map();
|
||||||
constructor(directives: CompileDirectiveMetadata[], private _exprParser: Parser,
|
constructor(directives: CompileDirectiveMetadata[], private _exprParser: Parser,
|
||||||
private _schemaRegistry: ElementSchemaRegistry) {
|
private _schemaRegistry: ElementSchemaRegistry) {
|
||||||
this.selectorMatcher = new SelectorMatcher();
|
this.selectorMatcher = new SelectorMatcher();
|
||||||
|
@ -103,7 +103,7 @@ class TemplateParseVisitor implements HtmlAstVisitor {
|
||||||
(directive: CompileDirectiveMetadata, index: number) => {
|
(directive: CompileDirectiveMetadata, index: number) => {
|
||||||
var selector = CssSelector.parse(directive.selector);
|
var selector = CssSelector.parse(directive.selector);
|
||||||
this.selectorMatcher.addSelectables(selector, directive);
|
this.selectorMatcher.addSelectables(selector, directive);
|
||||||
this.directivesIndexByTypeId.set(directive.type.id, index);
|
this.directivesIndex.set(directive, index);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,8 +397,7 @@ class TemplateParseVisitor implements HtmlAstVisitor {
|
||||||
} else if (!dir1Comp && dir2Comp) {
|
} else if (!dir1Comp && dir2Comp) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return this.directivesIndexByTypeId.get(dir1.type.id) -
|
return this.directivesIndex.get(dir1) - this.directivesIndex.get(dir2);
|
||||||
this.directivesIndexByTypeId.get(dir2.type.id);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return directives;
|
return directives;
|
||||||
|
|
|
@ -59,11 +59,11 @@ export function codeGenMapArray(argNames: string[], callback: string): string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function codeGenReplaceAll(pattern: string, value: string): string {
|
export function codeGenReplaceAll(pattern: string, expression: string): string {
|
||||||
if (IS_DART) {
|
if (IS_DART) {
|
||||||
return `.replaceAll('${pattern}', '${value}')`;
|
return `.replaceAll('${pattern}', ${expression})`;
|
||||||
} else {
|
} else {
|
||||||
return `.replace(/${pattern}/g, '${value}')`;
|
return `.replace(/${pattern}/g, ${expression})`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,6 +75,14 @@ export function codeGenValueFn(params: string[], value: string): string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function codeGenToString(expr: string): string {
|
||||||
|
if (IS_DART) {
|
||||||
|
return `'\${${expr}}'`;
|
||||||
|
} else {
|
||||||
|
// JS automatically convets to string...
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function splitAtColon(input: string, defaultValues: string[]): string[] {
|
export function splitAtColon(input: string, defaultValues: string[]): string[] {
|
||||||
var parts = StringWrapper.split(input.trim(), /\s*:\s*/g);
|
var parts = StringWrapper.split(input.trim(), /\s*:\s*/g);
|
||||||
|
|
|
@ -9,23 +9,48 @@ import {
|
||||||
RenderEmbeddedTemplateCmd
|
RenderEmbeddedTemplateCmd
|
||||||
} from 'angular2/src/core/render/render';
|
} from 'angular2/src/core/render/render';
|
||||||
|
|
||||||
|
var _nextTemplateId: number = 0;
|
||||||
|
|
||||||
|
export function nextTemplateId(): number {
|
||||||
|
return _nextTemplateId++;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A compiled template. This is const as we are storing it as annotation
|
* A compiled host template.
|
||||||
|
*
|
||||||
|
* This is const as we are storing it as annotation
|
||||||
* for the compiled component type.
|
* for the compiled component type.
|
||||||
*/
|
*/
|
||||||
@CONST()
|
@CONST()
|
||||||
export class CompiledTemplate {
|
export class CompiledHostTemplate {
|
||||||
static getChangeDetectorFromData(data: any[]): Function { return data[0]; }
|
// Note: _templateGetter is a function so that CompiledHostTemplate can be
|
||||||
static getCommandsFromData(data: any[]): TemplateCmd[] { return data[1]; }
|
// a const!
|
||||||
static getSylesFromData(data: any[]): string[] { return data[2]; }
|
constructor(private _templateGetter: Function) {}
|
||||||
|
|
||||||
|
getTemplate(): CompiledTemplate { return this._templateGetter(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A compiled template.
|
||||||
|
*/
|
||||||
|
export class CompiledTemplate {
|
||||||
// Note: paramGetter is a function so that we can have cycles between templates!
|
// Note: paramGetter is a function so that we can have cycles between templates!
|
||||||
// paramGetter returns a tuple with:
|
// paramGetter returns a tuple with:
|
||||||
// - ChangeDetector factory function
|
// - ChangeDetector factory function
|
||||||
// - TemplateCmd[]
|
// - TemplateCmd[]
|
||||||
// - styles
|
// - styles
|
||||||
constructor(public id: number,
|
constructor(public id: number,
|
||||||
public dataGetter: /*()=>[Function, TemplateCmd[], string[]]*/ Function) {}
|
private _dataGetter: /*()=>Array<Function, TemplateCmd[], string[]>*/ Function) {}
|
||||||
|
|
||||||
|
getData(appId: string): CompiledTemplateData {
|
||||||
|
var data = this._dataGetter(appId, this.id);
|
||||||
|
return new CompiledTemplateData(data[0], data[1], data[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class CompiledTemplateData {
|
||||||
|
constructor(public changeDetectorFactory: Function, public commands: TemplateCmd[],
|
||||||
|
public styles: string[]) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
const EMPTY_ARR = CONST_EXPR([]);
|
const EMPTY_ARR = CONST_EXPR([]);
|
||||||
|
|
|
@ -14,6 +14,7 @@ import {
|
||||||
} from 'angular2/test_lib';
|
} from 'angular2/test_lib';
|
||||||
|
|
||||||
import {CONST_EXPR, stringify, isType, Type, isBlank} from 'angular2/src/core/facade/lang';
|
import {CONST_EXPR, stringify, isType, Type, isBlank} from 'angular2/src/core/facade/lang';
|
||||||
|
import {MapWrapper} from 'angular2/src/core/facade/collection';
|
||||||
import {PromiseWrapper, Promise} from 'angular2/src/core/facade/async';
|
import {PromiseWrapper, Promise} from 'angular2/src/core/facade/async';
|
||||||
import {TemplateParser} from 'angular2/src/compiler/template_parser';
|
import {TemplateParser} from 'angular2/src/compiler/template_parser';
|
||||||
import {
|
import {
|
||||||
|
@ -61,12 +62,15 @@ export class RootComp {}
|
||||||
export class SomeDir {}
|
export class SomeDir {}
|
||||||
export class AComp {}
|
export class AComp {}
|
||||||
|
|
||||||
var RootCompTypeMeta = new CompileTypeMetadata(
|
var RootCompTypeMeta =
|
||||||
{id: 1, name: 'RootComp', runtime: RootComp, moduleId: THIS_MODULE_NAME});
|
new CompileTypeMetadata({name: 'RootComp', runtime: RootComp, moduleId: THIS_MODULE_NAME});
|
||||||
var SomeDirTypeMeta =
|
var SomeDirTypeMeta =
|
||||||
new CompileTypeMetadata({id: 2, name: 'SomeDir', runtime: SomeDir, moduleId: THIS_MODULE_NAME});
|
new CompileTypeMetadata({name: 'SomeDir', runtime: SomeDir, moduleId: THIS_MODULE_NAME});
|
||||||
var ACompTypeMeta =
|
var ACompTypeMeta =
|
||||||
new CompileTypeMetadata({id: 3, name: 'AComp', runtime: AComp, moduleId: THIS_MODULE_NAME});
|
new CompileTypeMetadata({name: 'AComp', runtime: AComp, moduleId: THIS_MODULE_NAME});
|
||||||
|
var compTypeTemplateId: Map<CompileTypeMetadata, number> =
|
||||||
|
MapWrapper.createFromPairs([[RootCompTypeMeta, 1], [SomeDirTypeMeta, 2], [ACompTypeMeta, 3]]);
|
||||||
|
const APP_ID = 'app1';
|
||||||
|
|
||||||
var NESTED_COMPONENT = new CompiledTemplate(45, () => []);
|
var NESTED_COMPONENT = new CompiledTemplate(45, () => []);
|
||||||
|
|
||||||
|
@ -221,7 +225,7 @@ export function main() {
|
||||||
run(rootComp, [])
|
run(rootComp, [])
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
expect(data).toEqual([
|
expect(data).toEqual([
|
||||||
[BEGIN_ELEMENT, 'div', ['_ngcontent-1', ''], [], [], [], false, null],
|
[BEGIN_ELEMENT, 'div', ['_ngcontent-app1-1', ''], [], [], [], false, null],
|
||||||
[END_ELEMENT]
|
[END_ELEMENT]
|
||||||
]);
|
]);
|
||||||
async.done();
|
async.done();
|
||||||
|
@ -283,7 +287,7 @@ export function main() {
|
||||||
[
|
[
|
||||||
BEGIN_COMPONENT,
|
BEGIN_COMPONENT,
|
||||||
'a',
|
'a',
|
||||||
['_nghost-3', '', '_ngcontent-1', ''],
|
['_nghost-app1-3', '', '_ngcontent-app1-1', ''],
|
||||||
[],
|
[],
|
||||||
[],
|
[],
|
||||||
['ACompType'],
|
['ACompType'],
|
||||||
|
@ -424,7 +428,7 @@ export function main() {
|
||||||
describe('compileComponentRuntime', () => {
|
describe('compileComponentRuntime', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
componentTemplateFactory = (directive: CompileDirectiveMetadata) => {
|
componentTemplateFactory = (directive: CompileDirectiveMetadata) => {
|
||||||
return new CompiledTemplate(directive.type.id, () => []);
|
return new CompiledTemplate(compTypeTemplateId.get(directive.type), () => []);
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -437,7 +441,8 @@ export function main() {
|
||||||
var parsedTemplate =
|
var parsedTemplate =
|
||||||
parser.parse(component.template.template, directives, component.type.name);
|
parser.parse(component.template.template, directives, component.type.name);
|
||||||
var commands = commandCompiler.compileComponentRuntime(
|
var commands = commandCompiler.compileComponentRuntime(
|
||||||
component, parsedTemplate, changeDetectorFactories, componentTemplateFactory);
|
component, APP_ID, compTypeTemplateId.get(component.type), parsedTemplate,
|
||||||
|
changeDetectorFactories, componentTemplateFactory);
|
||||||
return PromiseWrapper.resolve(humanize(commands));
|
return PromiseWrapper.resolve(humanize(commands));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,7 +453,7 @@ export function main() {
|
||||||
describe('compileComponentCodeGen', () => {
|
describe('compileComponentCodeGen', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
componentTemplateFactory = (directive: CompileDirectiveMetadata) => {
|
componentTemplateFactory = (directive: CompileDirectiveMetadata) => {
|
||||||
return `new ${TEMPLATE_COMMANDS_MODULE_REF}CompiledTemplate(${directive.type.id}, ${codeGenValueFn([], '{}')})`;
|
return `new ${TEMPLATE_COMMANDS_MODULE_REF}CompiledTemplate(${compTypeTemplateId.get(directive.type)}, ${codeGenValueFn([], '{}')})`;
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -461,7 +466,8 @@ export function main() {
|
||||||
var parsedTemplate =
|
var parsedTemplate =
|
||||||
parser.parse(component.template.template, directives, component.type.name);
|
parser.parse(component.template.template, directives, component.type.name);
|
||||||
var sourceModule = commandCompiler.compileComponentCodeGen(
|
var sourceModule = commandCompiler.compileComponentCodeGen(
|
||||||
component, parsedTemplate, changeDetectorFactoryExpressions, componentTemplateFactory);
|
component, `'${APP_ID}'`, `${compTypeTemplateId.get(component.type)}`, parsedTemplate,
|
||||||
|
changeDetectorFactoryExpressions, componentTemplateFactory);
|
||||||
var testableModule = createTestableModule(sourceModule).getSourceWithImports();
|
var testableModule = createTestableModule(sourceModule).getSourceWithImports();
|
||||||
return evalModule(testableModule.source, testableModule.imports, null);
|
return evalModule(testableModule.source, testableModule.imports, null);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ export function main() {
|
||||||
var fullDirectiveMeta: CompileDirectiveMetadata;
|
var fullDirectiveMeta: CompileDirectiveMetadata;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
fullTypeMeta = new CompileTypeMetadata({id: 23, name: 'SomeType', moduleId: 'someUrl'});
|
fullTypeMeta = new CompileTypeMetadata({name: 'SomeType', moduleId: 'someUrl'});
|
||||||
fullTemplateMeta = new CompileTemplateMetadata({
|
fullTemplateMeta = new CompileTemplateMetadata({
|
||||||
encapsulation: ViewEncapsulation.Emulated,
|
encapsulation: ViewEncapsulation.Emulated,
|
||||||
template: '<a></a>',
|
template: '<a></a>',
|
||||||
|
|
|
@ -42,7 +42,8 @@ const IMPORT_ABS_MODULE_NAME_WITH_IMPORT =
|
||||||
export function main() {
|
export function main() {
|
||||||
describe('StyleCompiler', () => {
|
describe('StyleCompiler', () => {
|
||||||
var xhr: SpyXHR;
|
var xhr: SpyXHR;
|
||||||
var typeMeta;
|
var templateId;
|
||||||
|
var appId;
|
||||||
|
|
||||||
beforeEachBindings(() => {
|
beforeEachBindings(() => {
|
||||||
xhr = <any>new SpyXHR();
|
xhr = <any>new SpyXHR();
|
||||||
|
@ -52,7 +53,8 @@ export function main() {
|
||||||
var compiler: StyleCompiler;
|
var compiler: StyleCompiler;
|
||||||
|
|
||||||
beforeEach(inject([StyleCompiler], (_compiler) => {
|
beforeEach(inject([StyleCompiler], (_compiler) => {
|
||||||
typeMeta = new CompileTypeMetadata({id: 23, moduleId: 'someUrl'});
|
templateId = 23;
|
||||||
|
appId = 'app1';
|
||||||
compiler = _compiler;
|
compiler = _compiler;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -81,8 +83,9 @@ export function main() {
|
||||||
return PromiseWrapper.resolve(response);
|
return PromiseWrapper.resolve(response);
|
||||||
});
|
});
|
||||||
return compiler.compileComponentRuntime(
|
return compiler.compileComponentRuntime(
|
||||||
typeMeta, new CompileTemplateMetadata(
|
appId, templateId,
|
||||||
{styles: styles, styleUrls: styleAbsUrls, encapsulation: encapsulation}));
|
new CompileTemplateMetadata(
|
||||||
|
{styles: styles, styleUrls: styleAbsUrls, encapsulation: encapsulation}));
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('no shim', () => {
|
describe('no shim', () => {
|
||||||
|
@ -121,8 +124,8 @@ export function main() {
|
||||||
compile(['div {\ncolor: red;\n}', 'span {\ncolor: blue;\n}'], [], encapsulation)
|
compile(['div {\ncolor: red;\n}', 'span {\ncolor: blue;\n}'], [], encapsulation)
|
||||||
.then(styles => {
|
.then(styles => {
|
||||||
compareStyles(styles, [
|
compareStyles(styles, [
|
||||||
'div[_ngcontent-23] {\ncolor: red;\n}',
|
'div[_ngcontent-app1-23] {\ncolor: red;\n}',
|
||||||
'span[_ngcontent-23] {\ncolor: blue;\n}'
|
'span[_ngcontent-app1-23] {\ncolor: blue;\n}'
|
||||||
]);
|
]);
|
||||||
async.done();
|
async.done();
|
||||||
});
|
});
|
||||||
|
@ -132,8 +135,8 @@ export function main() {
|
||||||
compile(['div {\ncolor: red;\n}'], [IMPORT_ABS_MODULE_NAME], encapsulation)
|
compile(['div {\ncolor: red;\n}'], [IMPORT_ABS_MODULE_NAME], encapsulation)
|
||||||
.then(styles => {
|
.then(styles => {
|
||||||
compareStyles(styles, [
|
compareStyles(styles, [
|
||||||
'div[_ngcontent-23] {\ncolor: red;\n}',
|
'div[_ngcontent-app1-23] {\ncolor: red;\n}',
|
||||||
'span[_ngcontent-23] {\ncolor: blue;\n}'
|
'span[_ngcontent-app1-23] {\ncolor: blue;\n}'
|
||||||
]);
|
]);
|
||||||
async.done();
|
async.done();
|
||||||
});
|
});
|
||||||
|
@ -143,9 +146,9 @@ export function main() {
|
||||||
compile(['div {\ncolor: red;\n}'], [IMPORT_ABS_MODULE_NAME_WITH_IMPORT], encapsulation)
|
compile(['div {\ncolor: red;\n}'], [IMPORT_ABS_MODULE_NAME_WITH_IMPORT], encapsulation)
|
||||||
.then(styles => {
|
.then(styles => {
|
||||||
compareStyles(styles, [
|
compareStyles(styles, [
|
||||||
'div[_ngcontent-23] {\ncolor: red;\n}',
|
'div[_ngcontent-app1-23] {\ncolor: red;\n}',
|
||||||
'a[_ngcontent-23] {\ncolor: green;\n}',
|
'a[_ngcontent-app1-23] {\ncolor: green;\n}',
|
||||||
'span[_ngcontent-23] {\ncolor: blue;\n}'
|
'span[_ngcontent-app1-23] {\ncolor: blue;\n}'
|
||||||
]);
|
]);
|
||||||
async.done();
|
async.done();
|
||||||
});
|
});
|
||||||
|
@ -198,8 +201,9 @@ export function main() {
|
||||||
function compile(styles: string[], styleAbsUrls: string[], encapsulation: ViewEncapsulation):
|
function compile(styles: string[], styleAbsUrls: string[], encapsulation: ViewEncapsulation):
|
||||||
Promise<string[]> {
|
Promise<string[]> {
|
||||||
var sourceExpression = compiler.compileComponentCodeGen(
|
var sourceExpression = compiler.compileComponentCodeGen(
|
||||||
typeMeta, new CompileTemplateMetadata(
|
`'${appId}'`, `${templateId}`,
|
||||||
{styles: styles, styleUrls: styleAbsUrls, encapsulation: encapsulation}));
|
new CompileTemplateMetadata(
|
||||||
|
{styles: styles, styleUrls: styleAbsUrls, encapsulation: encapsulation}));
|
||||||
var sourceWithImports = testableExpression(sourceExpression).getSourceWithImports();
|
var sourceWithImports = testableExpression(sourceExpression).getSourceWithImports();
|
||||||
return evalModule(sourceWithImports.source, sourceWithImports.imports, null);
|
return evalModule(sourceWithImports.source, sourceWithImports.imports, null);
|
||||||
};
|
};
|
||||||
|
@ -207,7 +211,7 @@ export function main() {
|
||||||
describe('no shim', () => {
|
describe('no shim', () => {
|
||||||
var encapsulation = ViewEncapsulation.None;
|
var encapsulation = ViewEncapsulation.None;
|
||||||
|
|
||||||
it('should compile plain css ruless', inject([AsyncTestCompleter], (async) => {
|
it('should compile plain css rules', inject([AsyncTestCompleter], (async) => {
|
||||||
compile(['div {color: red}', 'span {color: blue}'], [], encapsulation)
|
compile(['div {color: red}', 'span {color: blue}'], [], encapsulation)
|
||||||
.then(styles => {
|
.then(styles => {
|
||||||
expect(styles).toEqual(['div {color: red}', 'span {color: blue}']);
|
expect(styles).toEqual(['div {color: red}', 'span {color: blue}']);
|
||||||
|
@ -240,8 +244,8 @@ export function main() {
|
||||||
compile(['div {\ncolor: red;\n}', 'span {\ncolor: blue;\n}'], [], encapsulation)
|
compile(['div {\ncolor: red;\n}', 'span {\ncolor: blue;\n}'], [], encapsulation)
|
||||||
.then(styles => {
|
.then(styles => {
|
||||||
compareStyles(styles, [
|
compareStyles(styles, [
|
||||||
'div[_ngcontent-23] {\ncolor: red;\n}',
|
'div[_ngcontent-app1-23] {\ncolor: red;\n}',
|
||||||
'span[_ngcontent-23] {\ncolor: blue;\n}'
|
'span[_ngcontent-app1-23] {\ncolor: blue;\n}'
|
||||||
]);
|
]);
|
||||||
async.done();
|
async.done();
|
||||||
});
|
});
|
||||||
|
@ -251,8 +255,8 @@ export function main() {
|
||||||
compile(['div {color: red}'], [IMPORT_ABS_MODULE_NAME], encapsulation)
|
compile(['div {color: red}'], [IMPORT_ABS_MODULE_NAME], encapsulation)
|
||||||
.then(styles => {
|
.then(styles => {
|
||||||
compareStyles(styles, [
|
compareStyles(styles, [
|
||||||
'div[_ngcontent-23] {\ncolor: red;\n}',
|
'div[_ngcontent-app1-23] {\ncolor: red;\n}',
|
||||||
'span[_ngcontent-23] {\ncolor: blue;\n}'
|
'span[_ngcontent-app1-23] {\ncolor: blue;\n}'
|
||||||
]);
|
]);
|
||||||
async.done();
|
async.done();
|
||||||
});
|
});
|
||||||
|
|
|
@ -41,22 +41,25 @@ import {
|
||||||
CompiledTemplate
|
CompiledTemplate
|
||||||
} from 'angular2/src/core/compiler/template_commands';
|
} from 'angular2/src/core/compiler/template_commands';
|
||||||
|
|
||||||
import {Component, View, Directive} from 'angular2/core';
|
import {Component, View, Directive, bind} from 'angular2/core';
|
||||||
|
|
||||||
import {TEST_BINDINGS} from './test_bindings';
|
import {TEST_BINDINGS} from './test_bindings';
|
||||||
import {TestContext, TestDispatcher, TestPipes} from './change_detector_mocks';
|
import {TestContext, TestDispatcher, TestPipes} from './change_detector_mocks';
|
||||||
import {codeGenValueFn, codeGenExportVariable} from 'angular2/src/compiler/util';
|
import {codeGenValueFn, codeGenExportVariable} from 'angular2/src/compiler/util';
|
||||||
|
import {APP_ID} from 'angular2/src/core/render/dom/dom_tokens';
|
||||||
|
|
||||||
// Attention: This path has to point to this test file!
|
// Attention: This path has to point to this test file!
|
||||||
const THIS_MODULE = 'angular2/test/compiler/template_compiler_spec';
|
const THIS_MODULE = 'angular2/test/compiler/template_compiler_spec';
|
||||||
var THIS_MODULE_REF = moduleRef(THIS_MODULE);
|
var THIS_MODULE_REF = moduleRef(THIS_MODULE);
|
||||||
|
|
||||||
|
const APP_ID_VALUE = 'app1';
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe('TemplateCompiler', () => {
|
describe('TemplateCompiler', () => {
|
||||||
var compiler: TemplateCompiler;
|
var compiler: TemplateCompiler;
|
||||||
var runtimeMetadataResolver: RuntimeMetadataResolver;
|
var runtimeMetadataResolver: RuntimeMetadataResolver;
|
||||||
|
|
||||||
beforeEachBindings(() => TEST_BINDINGS);
|
beforeEachBindings(() => [bind(APP_ID).toValue(APP_ID_VALUE), TEST_BINDINGS]);
|
||||||
beforeEach(inject([TemplateCompiler, RuntimeMetadataResolver],
|
beforeEach(inject([TemplateCompiler, RuntimeMetadataResolver],
|
||||||
(_compiler, _runtimeMetadataResolver) => {
|
(_compiler, _runtimeMetadataResolver) => {
|
||||||
compiler = _compiler;
|
compiler = _compiler;
|
||||||
|
@ -125,7 +128,8 @@ export function main() {
|
||||||
|
|
||||||
describe('compileHostComponentRuntime', () => {
|
describe('compileHostComponentRuntime', () => {
|
||||||
function compile(components: Type[]): Promise<any[]> {
|
function compile(components: Type[]): Promise<any[]> {
|
||||||
return compiler.compileHostComponentRuntime(components[0]).then(humanizeTemplate);
|
return compiler.compileHostComponentRuntime(components[0])
|
||||||
|
.then((compiledHostTemplate) => humanizeTemplate(compiledHostTemplate.getTemplate()));
|
||||||
}
|
}
|
||||||
|
|
||||||
runTests(compile);
|
runTests(compile);
|
||||||
|
@ -307,7 +311,8 @@ class CompWithoutHost {
|
||||||
|
|
||||||
function testableTemplateModule(sourceModule: SourceModule, normComp: CompileDirectiveMetadata):
|
function testableTemplateModule(sourceModule: SourceModule, normComp: CompileDirectiveMetadata):
|
||||||
SourceModule {
|
SourceModule {
|
||||||
var resultExpression = `${THIS_MODULE_REF}humanizeTemplate(Host${normComp.type.name}Template)`;
|
var resultExpression =
|
||||||
|
`${THIS_MODULE_REF}humanizeTemplate(Host${normComp.type.name}Template.getTemplate())`;
|
||||||
var testableSource = `${sourceModule.sourceWithModuleRefs}
|
var testableSource = `${sourceModule.sourceWithModuleRefs}
|
||||||
${codeGenExportVariable('run')}${codeGenValueFn(['_'], resultExpression)};`;
|
${codeGenExportVariable('run')}${codeGenValueFn(['_'], resultExpression)};`;
|
||||||
return new SourceModule(sourceModule.moduleId, testableSource);
|
return new SourceModule(sourceModule.moduleId, testableSource);
|
||||||
|
@ -330,16 +335,15 @@ export function humanizeTemplate(template: CompiledTemplate,
|
||||||
if (isPresent(result)) {
|
if (isPresent(result)) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
var templateData = template.getData(APP_ID_VALUE);
|
||||||
var commands = [];
|
var commands = [];
|
||||||
var templateData = template.dataGetter();
|
|
||||||
result = {
|
result = {
|
||||||
'styles': CompiledTemplate.getSylesFromData(templateData),
|
'styles': templateData.styles,
|
||||||
'commands': commands,
|
'commands': commands,
|
||||||
'cd': testChangeDetector(CompiledTemplate.getChangeDetectorFromData(templateData))
|
'cd': testChangeDetector(templateData.changeDetectorFactory)
|
||||||
};
|
};
|
||||||
humanizedTemplates.set(template.id, result);
|
humanizedTemplates.set(template.id, result);
|
||||||
visitAllCommands(new CommandHumanizer(commands, humanizedTemplates),
|
visitAllCommands(new CommandHumanizer(commands, humanizedTemplates), templateData.commands);
|
||||||
CompiledTemplate.getCommandsFromData(templateData));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -322,11 +322,11 @@ export function main() {
|
||||||
it('should locate directives components first and ordered by the directives array in the View',
|
it('should locate directives components first and ordered by the directives array in the View',
|
||||||
() => {
|
() => {
|
||||||
var dirA = CompileDirectiveMetadata.create(
|
var dirA = CompileDirectiveMetadata.create(
|
||||||
{selector: '[a]', type: new CompileTypeMetadata({name: 'DirA', id: 3})});
|
{selector: '[a]', type: new CompileTypeMetadata({name: 'DirA'})});
|
||||||
var dirB = CompileDirectiveMetadata.create(
|
var dirB = CompileDirectiveMetadata.create(
|
||||||
{selector: '[b]', type: new CompileTypeMetadata({name: 'DirB', id: 2})});
|
{selector: '[b]', type: new CompileTypeMetadata({name: 'DirB'})});
|
||||||
var dirC = CompileDirectiveMetadata.create(
|
var dirC = CompileDirectiveMetadata.create(
|
||||||
{selector: '[c]', type: new CompileTypeMetadata({name: 'DirC', id: 1})});
|
{selector: '[c]', type: new CompileTypeMetadata({name: 'DirC'})});
|
||||||
var comp = CompileDirectiveMetadata.create({
|
var comp = CompileDirectiveMetadata.create({
|
||||||
selector: 'div',
|
selector: 'div',
|
||||||
isComponent: true,
|
isComponent: true,
|
||||||
|
|
Loading…
Reference in New Issue