Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions modules/angular2/src/compiler/change_definition_factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
ASTWithSource
} from 'angular2/src/core/change_detection/change_detection';

import {DirectiveMetadata, TypeMetadata} from './api';
import {NormalizedDirectiveMetadata, TypeMetadata} from './directive_metadata';
import {
TemplateAst,
ElementAst,
Expand Down Expand Up @@ -203,5 +203,5 @@ function _collectNestedProtoViewsVariableNames(pvVisitors: ProtoViewVisitor[]):


function _protoViewId(hostComponentType: TypeMetadata, pvIndex: number, viewType: string): string {
return `${hostComponentType.typeName}_${viewType}_${pvIndex}`;
return `${hostComponentType.name}_${viewType}_${pvIndex}`;
}
36 changes: 18 additions & 18 deletions modules/angular2/src/compiler/change_detector_compiler.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {TypeMetadata, SourceModule} from './api';
import {TypeMetadata} from './directive_metadata';
import {SourceExpression, moduleRef} from './source_module';
import {
ChangeDetectorJITGenerator
} from 'angular2/src/core/change_detection/change_detection_jit_generator';
Expand All @@ -15,20 +16,19 @@ import {

import {TemplateAst} from './template_ast';
import {Codegen} from 'angular2/src/transform/template_compiler/change_detector_codegen';

var IS_DART = !isJsObject({});
import {IS_DART} from './util';
import {Injectable} from 'angular2/src/core/di';

const ABSTRACT_CHANGE_DETECTOR = "AbstractChangeDetector";
const UTIL = "ChangeDetectionUtil";

const JS_CHANGE_DETECTOR_IMPORTS = CONST_EXPR([
['angular2/src/core/change_detection/abstract_change_detector', 'acd'],
['angular2/src/core/change_detection/change_detection_util', 'cdu']
]);

const DART_CHANGE_DETECTOR_IMPORTS =
CONST_EXPR([['angular2/src/core/change_detection/pregen_proto_change_detector', '_gen']]);
var ABSTRACT_CHANGE_DETECTOR_MODULE =
moduleRef('angular2/src/core/change_detection/abstract_change_detector');
var UTIL_MODULE = moduleRef('angular2/src/core/change_detection/change_detection_util');
var PREGEN_PROTO_CHANGE_DETECTOR_MODULE =
moduleRef('angular2/src/core/change_detection/pregen_proto_change_detector');

@Injectable()
export class ChangeDetectionCompiler {
constructor(private _genConfig: ChangeDetectorGenConfig) {}

Expand All @@ -52,30 +52,30 @@ export class ChangeDetectionCompiler {
}

compileComponentCodeGen(componentType: TypeMetadata, strategy: ChangeDetectionStrategy,
parsedTemplate: TemplateAst[]): SourceModule {
parsedTemplate: TemplateAst[]): SourceExpression {
var changeDetectorDefinitions =
createChangeDetectorDefinitions(componentType, strategy, this._genConfig, parsedTemplate);
var imports = IS_DART ? DART_CHANGE_DETECTOR_IMPORTS : JS_CHANGE_DETECTOR_IMPORTS;
var factories = [];
var sourceParts = changeDetectorDefinitions.map(definition => {
var codegen: any;
// TODO(tbosch): move the 2 code generators to the same place, one with .dart and one with .ts
// suffix
// and have the same API for calling them!
if (IS_DART) {
codegen = new Codegen();
codegen = new Codegen(PREGEN_PROTO_CHANGE_DETECTOR_MODULE);
var className = definition.id;
codegen.generate(componentType.typeName, className, definition);
codegen.generate(componentType.name, className, definition);
factories.push(`(dispatcher) => new ${className}(dispatcher)`);
return codegen.toString();
} else {
codegen = new ChangeDetectorJITGenerator(definition, `cdu.${UTIL}`,
`acd.${ABSTRACT_CHANGE_DETECTOR}`);
codegen = new ChangeDetectorJITGenerator(
definition, `${UTIL_MODULE}${UTIL}`,
`${ABSTRACT_CHANGE_DETECTOR_MODULE}${ABSTRACT_CHANGE_DETECTOR}`);
factories.push(`function(dispatcher) { return new ${codegen.typeName}(dispatcher); }`);
return codegen.generateSource();
}
});
sourceParts.push(`var CHANGE_DETECTORS = [ ${factories.join(',')} ];`);
return new SourceModule(componentType.typeUrl, sourceParts.join('\n'), imports);
var expression = `[ ${factories.join(',')} ]`;
return new SourceExpression(sourceParts, expression);
}
}
101 changes: 49 additions & 52 deletions modules/angular2/src/compiler/command_compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,80 +25,80 @@ import {
BoundDirectivePropertyAst,
templateVisitAll
} from './template_ast';
import {SourceModule, DirectiveMetadata, TypeMetadata} from './api';
import {TypeMetadata, NormalizedDirectiveMetadata} from './directive_metadata';
import {SourceExpression, moduleRef} from './source_module';

import {ViewEncapsulation} from 'angular2/src/core/render/api';
import {shimHostAttribute, shimContentAttribute} from './style_compiler';
import {escapeSingleQuoteString} from './util';
import {Injectable} from 'angular2/src/core/di';

const TEMPLATE_COMMANDS_MODULE = 'angular2/src/core/compiler/template_commands';
const TEMPLATE_COMMANDS_MODULE_ALIAS = 'tc';
export var TEMPLATE_COMMANDS_MODULE_REF = moduleRef('angular2/src/core/compiler/template_commands');

@Injectable()
export class CommandCompiler {
compileComponentRuntime(component: DirectiveMetadata, template: TemplateAst[],
compileComponentRuntime(component: NormalizedDirectiveMetadata, template: TemplateAst[],
componentTemplateFactory: Function): TemplateCmd[] {
var visitor =
new CommandBuilderVisitor(new RuntimeCommandFactory(componentTemplateFactory), component);
templateVisitAll(visitor, template);
return visitor.result;
}

compileComponentCodeGen(component: DirectiveMetadata, template: TemplateAst[],
componentTemplateFactory: Function): SourceModule {
var imports: string[][] = [[TEMPLATE_COMMANDS_MODULE, TEMPLATE_COMMANDS_MODULE_ALIAS]];
var visitor = new CommandBuilderVisitor(
new CodegenCommandFactory(componentTemplateFactory, TEMPLATE_COMMANDS_MODULE_ALIAS,
imports),
component);
compileComponentCodeGen(component: NormalizedDirectiveMetadata, template: TemplateAst[],
componentTemplateFactory: Function): SourceExpression {
var visitor =
new CommandBuilderVisitor(new CodegenCommandFactory(componentTemplateFactory), component);
templateVisitAll(visitor, template);
var source = `var COMMANDS = [${visitor.result.join(',')}];`;
return new SourceModule(null, source, imports);
var source = `[${visitor.result.join(',')}]`;
return new SourceExpression([], source);
}
}

interface CommandFactory<R> {
createText(value: string, isBound: boolean, ngContentIndex: number): R;
createNgContent(ngContentIndex: number): R;
createBeginElement(name: string, attrNameAndValues: string[], eventNames: string[],
variableNameAndValues: string[], directives: TypeMetadata[], isBound: boolean,
ngContentIndex: number): R;
variableNameAndValues: string[], directives: NormalizedDirectiveMetadata[],
isBound: boolean, ngContentIndex: number): R;
createEndElement(): R;
createBeginComponent(name: string, attrNameAndValues: string[], eventNames: string[],
variableNameAndValues: string[], directives: TypeMetadata[],
variableNameAndValues: string[], directives: NormalizedDirectiveMetadata[],
nativeShadow: boolean, ngContentIndex: number): R;
createEndComponent(): R;
createEmbeddedTemplate(attrNameAndValues: string[], variableNameAndValues: string[],
directives: TypeMetadata[], isMerged: boolean, ngContentIndex: number,
children: R[]): R;
directives: NormalizedDirectiveMetadata[], isMerged: boolean,
ngContentIndex: number, children: R[]): R;
}

class RuntimeCommandFactory implements CommandFactory<TemplateCmd> {
constructor(public componentTemplateFactory: Function) {}
private _mapDirectives(directives: TypeMetadata[]): Type[] {
return directives.map(directive => directive.type);
private _mapDirectives(directives: NormalizedDirectiveMetadata[]): Type[] {
return directives.map(directive => directive.type.runtime);
}

createText(value: string, isBound: boolean, ngContentIndex: number): TemplateCmd {
return text(value, isBound, ngContentIndex);
}
createNgContent(ngContentIndex: number): TemplateCmd { return ngContent(ngContentIndex); }
createBeginElement(name: string, attrNameAndValues: string[], eventNames: string[],
variableNameAndValues: string[], directives: TypeMetadata[], isBound: boolean,
ngContentIndex: number): TemplateCmd {
variableNameAndValues: string[], directives: NormalizedDirectiveMetadata[],
isBound: boolean, ngContentIndex: number): TemplateCmd {
return beginElement(name, attrNameAndValues, eventNames, variableNameAndValues,
this._mapDirectives(directives), isBound, ngContentIndex);
}
createEndElement(): TemplateCmd { return endElement(); }
createBeginComponent(name: string, attrNameAndValues: string[], eventNames: string[],
variableNameAndValues: string[], directives: TypeMetadata[],
variableNameAndValues: string[], directives: NormalizedDirectiveMetadata[],
nativeShadow: boolean, ngContentIndex: number): TemplateCmd {
return beginComponent(name, attrNameAndValues, eventNames, variableNameAndValues,
this._mapDirectives(directives), nativeShadow, ngContentIndex,
this.componentTemplateFactory(directives[0]));
}
createEndComponent(): TemplateCmd { return endComponent(); }
createEmbeddedTemplate(attrNameAndValues: string[], variableNameAndValues: string[],
directives: TypeMetadata[], isMerged: boolean, ngContentIndex: number,
children: TemplateCmd[]): TemplateCmd {
directives: NormalizedDirectiveMetadata[], isMerged: boolean,
ngContentIndex: number, children: TemplateCmd[]): TemplateCmd {
return embeddedTemplate(attrNameAndValues, variableNameAndValues,
this._mapDirectives(directives), isMerged, ngContentIndex, children);
}
Expand All @@ -109,42 +109,38 @@ function escapeStringArray(data: string[]): string {
}

class CodegenCommandFactory implements CommandFactory<string> {
constructor(public componentTemplateFactory: Function, public templateCommandsModuleAlias,
public imports: string[][]) {}

private _escapeDirectives(directives: TypeMetadata[]): string[] {
return directives.map(directiveType => {
var importAlias = `dir${this.imports.length}`;
this.imports.push([directiveType.typeUrl, importAlias]);
return `${importAlias}.${directiveType.typeName}`;
});
}
constructor(public componentTemplateFactory: Function) {}

createText(value: string, isBound: boolean, ngContentIndex: number): string {
return `${this.templateCommandsModuleAlias}.text(${escapeSingleQuoteString(value)}, ${isBound}, ${ngContentIndex})`;
return `${TEMPLATE_COMMANDS_MODULE_REF}text(${escapeSingleQuoteString(value)}, ${isBound}, ${ngContentIndex})`;
}
createNgContent(ngContentIndex: number): string {
return `${this.templateCommandsModuleAlias}.ngContent(${ngContentIndex})`;
return `${TEMPLATE_COMMANDS_MODULE_REF}ngContent(${ngContentIndex})`;
}
createBeginElement(name: string, attrNameAndValues: string[], eventNames: string[],
variableNameAndValues: string[], directives: TypeMetadata[], isBound: boolean,
ngContentIndex: number): string {
return `${this.templateCommandsModuleAlias}.beginElement(${escapeSingleQuoteString(name)}, ${escapeStringArray(attrNameAndValues)}, ${escapeStringArray(eventNames)}, ${escapeStringArray(variableNameAndValues)}, [${this._escapeDirectives(directives).join(',')}], ${isBound}, ${ngContentIndex})`;
variableNameAndValues: string[], directives: NormalizedDirectiveMetadata[],
isBound: boolean, ngContentIndex: number): string {
return `${TEMPLATE_COMMANDS_MODULE_REF}beginElement(${escapeSingleQuoteString(name)}, ${escapeStringArray(attrNameAndValues)}, ${escapeStringArray(eventNames)}, ${escapeStringArray(variableNameAndValues)}, [${_escapeDirectives(directives).join(',')}], ${isBound}, ${ngContentIndex})`;
}
createEndElement(): string { return `${this.templateCommandsModuleAlias}.endElement()`; }
createEndElement(): string { return `${TEMPLATE_COMMANDS_MODULE_REF}endElement()`; }
createBeginComponent(name: string, attrNameAndValues: string[], eventNames: string[],
variableNameAndValues: string[], directives: TypeMetadata[],
variableNameAndValues: string[], directives: NormalizedDirectiveMetadata[],
nativeShadow: boolean, ngContentIndex: number): string {
return `${this.templateCommandsModuleAlias}.beginComponent(${escapeSingleQuoteString(name)}, ${escapeStringArray(attrNameAndValues)}, ${escapeStringArray(eventNames)}, ${escapeStringArray(variableNameAndValues)}, [${this._escapeDirectives(directives).join(',')}], ${nativeShadow}, ${ngContentIndex}, ${this.componentTemplateFactory(directives[0], this.imports)})`;
return `${TEMPLATE_COMMANDS_MODULE_REF}beginComponent(${escapeSingleQuoteString(name)}, ${escapeStringArray(attrNameAndValues)}, ${escapeStringArray(eventNames)}, ${escapeStringArray(variableNameAndValues)}, [${_escapeDirectives(directives).join(',')}], ${nativeShadow}, ${ngContentIndex}, ${this.componentTemplateFactory(directives[0])})`;
}
createEndComponent(): string { return `${this.templateCommandsModuleAlias}.endComponent()`; }
createEndComponent(): string { return `${TEMPLATE_COMMANDS_MODULE_REF}endComponent()`; }
createEmbeddedTemplate(attrNameAndValues: string[], variableNameAndValues: string[],
directives: TypeMetadata[], isMerged: boolean, ngContentIndex: number,
children: string[]): string {
return `${this.templateCommandsModuleAlias}.embeddedTemplate(${escapeStringArray(attrNameAndValues)}, ${escapeStringArray(variableNameAndValues)}, [${this._escapeDirectives(directives).join(',')}], ${isMerged}, ${ngContentIndex}, [${children.join(',')}])`;
directives: NormalizedDirectiveMetadata[], isMerged: boolean,
ngContentIndex: number, children: string[]): string {
return `${TEMPLATE_COMMANDS_MODULE_REF}embeddedTemplate(${escapeStringArray(attrNameAndValues)}, ${escapeStringArray(variableNameAndValues)}, [${_escapeDirectives(directives).join(',')}], ${isMerged}, ${ngContentIndex}, [${children.join(',')}])`;
}
}

function _escapeDirectives(directives: NormalizedDirectiveMetadata[]): 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);
Expand All @@ -154,18 +150,19 @@ function visitAndReturnContext(visitor: TemplateAstVisitor, asts: TemplateAst[],
class CommandBuilderVisitor<R> implements TemplateAstVisitor {
result: R[] = [];
transitiveNgContentCount: number = 0;
constructor(public commandFactory: CommandFactory<R>, public component: DirectiveMetadata) {}
constructor(public commandFactory: CommandFactory<R>,
public component: NormalizedDirectiveMetadata) {}

private _readAttrNameAndValues(localComponent: DirectiveMetadata,
private _readAttrNameAndValues(localComponent: NormalizedDirectiveMetadata,
attrAsts: TemplateAst[]): string[] {
var attrNameAndValues: string[] = visitAndReturnContext(this, attrAsts, []);
if (isPresent(localComponent) &&
localComponent.template.encapsulation === ViewEncapsulation.Emulated) {
attrNameAndValues.push(shimHostAttribute(localComponent.type));
attrNameAndValues.push(shimHostAttribute(localComponent.type.id));
attrNameAndValues.push('');
}
if (this.component.template.encapsulation === ViewEncapsulation.Emulated) {
attrNameAndValues.push(shimContentAttribute(this.component.type));
attrNameAndValues.push(shimContentAttribute(this.component.type.id));
attrNameAndValues.push('');
}
return attrNameAndValues;
Expand Down Expand Up @@ -228,7 +225,7 @@ class CommandBuilderVisitor<R> implements TemplateAstVisitor {
return null;
}
visitDirective(ast: DirectiveAst, directivesAndEventNames: any[][]): any {
directivesAndEventNames[0].push(ast.directive.type);
directivesAndEventNames[0].push(ast.directive);
templateVisitAll(this, ast.hostEvents, directivesAndEventNames[1]);
return null;
}
Expand Down
9 changes: 9 additions & 0 deletions modules/angular2/src/compiler/compiler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export {TemplateCompiler} from './template_compiler';
export {
DirectiveMetadata,
TypeMetadata,
TemplateMetadata,
ChangeDetectionMetadata,
INormalizedDirectiveMetadata
} from './directive_metadata';
export {SourceModule, SourceWithImports} from './source_module';
Loading