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