Skip to content

Commit

Permalink
refactor(compiler): use the new compiler everywhere
Browse files Browse the repository at this point in the history
Closes angular#3605

BREAKING CHANGE:
- we don't mark an element as bound any more if it only contains text bindings
  E.g. <div>{{hello}}</div>
  This changes the indices when using `DebugElement.componentViewChildren` / `DebugElement.children`.
- `@Directive.compileChildren` was removed,
  `ng-non-bindable` is now builtin and not a directive any more
- angular no more adds the `ng-binding` class to elements with bindings
- directives are now ordered as they are listed in the View.directives regarding change detection.
  Previously they had an undefined order.
- the `Renderer` interface has new methods `createProtoView` and `registerComponentTemplate`. See `DomRenderer` for default implementations.
- reprojection with `ng-content` is now all or nothing per `ng-content` element
- angular2 transformer can't be used in tests that modify directive metadata.
  Use `angular2/src/transform/inliner_for_test` transformer instead.
  • Loading branch information
tbosch committed Oct 2, 2015
1 parent 61ba63c commit 681f69c
Show file tree
Hide file tree
Showing 123 changed files with 2,012 additions and 3,451 deletions.
9 changes: 1 addition & 8 deletions modules/angular2/src/compiler/change_definition_factory.ts
Expand Up @@ -189,8 +189,7 @@ function createChangeDefinitions(pvVisitors: ProtoViewVisitor[], componentType:
genConfig: ChangeDetectorGenConfig): ChangeDetectorDefinition[] {
var pvVariableNames = _collectNestedProtoViewsVariableNames(pvVisitors);
return pvVisitors.map(pvVisitor => {
var viewType = pvVisitor.viewIndex === 0 ? 'component' : 'embedded';
var id = _protoViewId(componentType, pvVisitor.viewIndex, viewType);
var id = `${componentType.name}_${pvVisitor.viewIndex}`;
return new ChangeDetectorDefinition(
id, pvVisitor.strategy, pvVariableNames[pvVisitor.viewIndex], pvVisitor.bindingRecords,
pvVisitor.eventRecords, pvVisitor.directiveRecords, genConfig);
Expand All @@ -207,9 +206,3 @@ function _collectNestedProtoViewsVariableNames(pvVisitors: ProtoViewVisitor[]):
});
return nestedPvVariableNames;
}


function _protoViewId(hostComponentType: CompileTypeMetadata, pvIndex: number, viewType: string):
string {
return `${hostComponentType.name}_${viewType}_${pvIndex}`;
}
26 changes: 17 additions & 9 deletions modules/angular2/src/compiler/change_detector_compiler.ts
Expand Up @@ -16,17 +16,18 @@ import {

import {TemplateAst} from './template_ast';
import {Codegen} from 'angular2/src/transform/template_compiler/change_detector_codegen';
import {IS_DART} from './util';
import {IS_DART, MODULE_SUFFIX} from './util';
import {Injectable} from 'angular2/src/core/di';

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

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');
var ABSTRACT_CHANGE_DETECTOR_MODULE = moduleRef(
`package:angular2/src/core/change_detection/abstract_change_detector${MODULE_SUFFIX}`);
var UTIL_MODULE =
moduleRef(`package:angular2/src/core/change_detection/change_detection_util${MODULE_SUFFIX}`);
var PREGEN_PROTO_CHANGE_DETECTOR_MODULE = moduleRef(
`package:angular2/src/core/change_detection/pregen_proto_change_detector${MODULE_SUFFIX}`);

@Injectable()
export class ChangeDetectionCompiler {
Expand Down Expand Up @@ -54,24 +55,31 @@ export class ChangeDetectionCompiler {
var changeDetectorDefinitions =
createChangeDetectorDefinitions(componentType, strategy, this._genConfig, parsedTemplate);
var factories = [];
var index = 0;
var sourceParts = changeDetectorDefinitions.map(definition => {
var codegen: any;
var sourcePart;
// 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(PREGEN_PROTO_CHANGE_DETECTOR_MODULE);
var className = definition.id;
codegen.generate(componentType.name, className, definition);
var typeRef = (index === 0 && componentType.isHost) ?
'dynamic' :
`${moduleRef(componentType.moduleUrl)}${componentType.name}`;
codegen.generate(typeRef, className, definition);
factories.push(`(dispatcher) => new ${className}(dispatcher)`);
return codegen.toString();
sourcePart = codegen.toString();
} else {
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();
sourcePart = codegen.generateSource();
}
index++;
return sourcePart;
});
return new SourceExpressions(sourceParts, factories);
}
Expand Down
7 changes: 4 additions & 3 deletions modules/angular2/src/compiler/command_compiler.ts
Expand Up @@ -37,10 +37,11 @@ import {
shimContentAttributeExpr,
shimHostAttributeExpr
} from './style_compiler';
import {escapeSingleQuoteString} from './util';
import {escapeSingleQuoteString, MODULE_SUFFIX} from './util';
import {Injectable} from 'angular2/src/core/di';

export var TEMPLATE_COMMANDS_MODULE_REF = moduleRef('angular2/src/core/compiler/template_commands');
export var TEMPLATE_COMMANDS_MODULE_REF =
moduleRef(`package:angular2/src/core/compiler/template_commands${MODULE_SUFFIX}`);

const IMPLICIT_TEMPLATE_VAR = '\$implicit';

Expand Down Expand Up @@ -353,6 +354,6 @@ function codeGenArray(data: any[]): string {

function codeGenDirectivesArray(directives: CompileDirectiveMetadata[]): string {
var expressions = directives.map(
directiveType => `${moduleRef(directiveType.type.moduleId)}${directiveType.type.name}`);
directiveType => `${moduleRef(directiveType.type.moduleUrl)}${directiveType.type.name}`);
return `[${expressions.join(',')}]`;
}
10 changes: 10 additions & 0 deletions modules/angular2/src/compiler/compiler.ts
Expand Up @@ -17,6 +17,12 @@ import {StyleCompiler} from 'angular2/src/compiler/style_compiler';
import {CommandCompiler} from 'angular2/src/compiler/command_compiler';
import {TemplateCompiler} from 'angular2/src/compiler/template_compiler';
import {ChangeDetectorGenConfig} from 'angular2/src/core/change_detection/change_detection';
import {Compiler} from 'angular2/src/core/compiler/compiler';
import {RuntimeCompiler} from 'angular2/src/compiler/runtime_compiler';
import {ElementSchemaRegistry} from 'angular2/src/core/render/dom/schema/element_schema_registry';
import {
DomElementSchemaRegistry
} from 'angular2/src/core/render/dom/schema/dom_element_schema_registry';

export function compilerBindings(): Array<Type | Binding | any[]> {
return [
Expand All @@ -31,5 +37,9 @@ export function compilerBindings(): Array<Type | Binding | any[]> {
.toValue(
new ChangeDetectorGenConfig(assertionsEnabled(), assertionsEnabled(), false, true)),
TemplateCompiler,
RuntimeCompiler,
bind(Compiler).toAlias(RuntimeCompiler),
DomElementSchemaRegistry,
bind(ElementSchemaRegistry).toAlias(DomElementSchemaRegistry)
];
}
23 changes: 16 additions & 7 deletions modules/angular2/src/compiler/directive_metadata.ts
Expand Up @@ -24,22 +24,27 @@ var HOST_REG_EXP = /^(?:(?:\[([^\]]+)\])|(?:\(([^\)]+)\)))$/g;
export class CompileTypeMetadata {
runtime: Type;
name: string;
moduleId: string;
constructor({runtime, name, moduleId}: {runtime?: Type, name?: string, moduleId?: string} = {}) {
moduleUrl: string;
isHost: boolean;
constructor({runtime, name, moduleUrl, isHost}:
{runtime?: Type, name?: string, moduleUrl?: string, isHost?: boolean} = {}) {
this.runtime = runtime;
this.name = name;
this.moduleId = moduleId;
this.moduleUrl = moduleUrl;
this.isHost = normalizeBool(isHost);
}

static fromJson(data: StringMap<string, any>): CompileTypeMetadata {
return new CompileTypeMetadata({name: data['name'], moduleId: data['moduleId']});
return new CompileTypeMetadata(
{name: data['name'], moduleUrl: data['moduleUrl'], isHost: data['isHost']});
}

toJson(): StringMap<string, any> {
return {
// Note: Runtime type can't be serialized...
'name': this.name,
'moduleId': this.moduleId
'moduleUrl': this.moduleUrl,
'isHost': this.isHost
};
}
}
Expand Down Expand Up @@ -248,8 +253,12 @@ export function createHostComponentMeta(componentType: CompileTypeMetadata,
componentSelector: string): CompileDirectiveMetadata {
var template = CssSelector.parse(componentSelector)[0].getMatchingElementTemplate();
return CompileDirectiveMetadata.create({
type: new CompileTypeMetadata(
{runtime: Object, name: `Host${componentType.name}`, moduleId: componentType.moduleId}),
type: new CompileTypeMetadata({
runtime: Object,
name: `Host${componentType.name}`,
moduleUrl: componentType.moduleUrl,
isHost: true
}),
template: new CompileTemplateMetadata(
{template: template, templateUrl: '', styles: [], styleUrls: [], ngContentSelectors: []}),
changeDetection: ChangeDetectionStrategy.Default,
Expand Down
28 changes: 28 additions & 0 deletions modules/angular2/src/compiler/runtime_compiler.ts
@@ -0,0 +1,28 @@
import {Compiler, internalCreateProtoView} from 'angular2/src/core/compiler/compiler';
import {ProtoViewRef} from 'angular2/src/core/compiler/view_ref';
import {ProtoViewFactory} from 'angular2/src/core/compiler/proto_view_factory';
import {TemplateCompiler} from './template_compiler';

import {Injectable} from 'angular2/src/core/di';
import {Type} from 'angular2/src/core/facade/lang';
import {Promise, PromiseWrapper} from 'angular2/src/core/facade/async';

@Injectable()
export class RuntimeCompiler extends Compiler {
/**
* @private
*/
constructor(_protoViewFactory: ProtoViewFactory, private _templateCompiler: TemplateCompiler) {
super(_protoViewFactory);
}

compileInHost(componentType: Type): Promise<ProtoViewRef> {
return this._templateCompiler.compileHostComponentRuntime(componentType)
.then(compiledHostTemplate => internalCreateProtoView(this, compiledHostTemplate));
}

clearCache() {
super.clearCache();
this._templateCompiler.clearCache();
}
}
11 changes: 6 additions & 5 deletions modules/angular2/src/compiler/runtime_metadata.ts
Expand Up @@ -18,6 +18,7 @@ import {hasLifecycleHook} from 'angular2/src/core/compiler/directive_lifecycle_r
import {LifecycleHooks, LIFECYCLE_HOOKS_VALUES} from 'angular2/src/core/compiler/interfaces';
import {reflector} from 'angular2/src/core/reflection/reflection';
import {Injectable} from 'angular2/src/core/di';
import {MODULE_SUFFIX} from './util';

// group 1: "property" from "[property]"
// group 2: "event" from "(event)"
Expand All @@ -33,7 +34,7 @@ export class RuntimeMetadataResolver {
var meta = this._cache.get(directiveType);
if (isBlank(meta)) {
var directiveAnnotation = this._directiveResolver.resolve(directiveType);
var moduleId = calcModuleId(directiveType, directiveAnnotation);
var moduleUrl = calcModuleUrl(directiveType, directiveAnnotation);
var templateMeta = null;
var changeDetectionStrategy = null;

Expand All @@ -55,7 +56,7 @@ export class RuntimeMetadataResolver {
isComponent: isPresent(templateMeta),
dynamicLoadable: true,
type: new cpl.CompileTypeMetadata(
{name: stringify(directiveType), moduleId: moduleId, runtime: directiveType}),
{name: stringify(directiveType), moduleUrl: moduleUrl, runtime: directiveType}),
template: templateMeta,
changeDetection: changeDetectionStrategy,
inputs: directiveAnnotation.inputs,
Expand Down Expand Up @@ -111,10 +112,10 @@ function isValidDirective(value: Type): boolean {
return isPresent(value) && (value instanceof Type);
}

function calcModuleId(type: Type, directiveAnnotation: dirAnn.DirectiveMetadata): string {
function calcModuleUrl(type: Type, directiveAnnotation: dirAnn.DirectiveMetadata): string {
if (isPresent(directiveAnnotation.moduleId)) {
return directiveAnnotation.moduleId;
return `package:${directiveAnnotation.moduleId}${MODULE_SUFFIX}`;
} else {
return reflector.moduleId(type);
return reflector.importUri(type);
}
}
16 changes: 8 additions & 8 deletions modules/angular2/src/compiler/source_module.ts
Expand Up @@ -2,28 +2,28 @@ import {StringWrapper, isBlank} from 'angular2/src/core/facade/lang';

var MODULE_REGEXP = /#MODULE\[([^\]]*)\]/g;

export function moduleRef(moduleId): string {
return `#MODULE[${moduleId}]`;
export function moduleRef(moduleUrl): string {
return `#MODULE[${moduleUrl}]`;
}

export class SourceModule {
constructor(public moduleId: string, public sourceWithModuleRefs: string) {}
constructor(public moduleUrl: string, public sourceWithModuleRefs: string) {}

getSourceWithImports(): SourceWithImports {
var moduleAliases = {};
var imports: string[][] = [];
var newSource =
StringWrapper.replaceAllMapped(this.sourceWithModuleRefs, MODULE_REGEXP, (match) => {
var moduleId = match[1];
var alias = moduleAliases[moduleId];
var moduleUrl = match[1];
var alias = moduleAliases[moduleUrl];
if (isBlank(alias)) {
if (moduleId == this.moduleId) {
if (moduleUrl == this.moduleUrl) {
alias = '';
} else {
alias = `import${imports.length}`;
imports.push([moduleId, alias]);
imports.push([moduleUrl, alias]);
}
moduleAliases[moduleId] = alias;
moduleAliases[moduleUrl] = alias;
}
return alias.length > 0 ? `${alias}.` : '';
});
Expand Down
29 changes: 16 additions & 13 deletions modules/angular2/src/compiler/style_compiler.ts
Expand Up @@ -14,7 +14,8 @@ import {
codeGenMapArray,
codeGenReplaceAll,
codeGenExportVariable,
codeGenToString
codeGenToString,
MODULE_SUFFIX
} from './util';
import {Injectable} from 'angular2/src/core/di';

Expand Down Expand Up @@ -56,13 +57,15 @@ export class StyleCompiler {
return this._styleCodeGen(template.styles, template.styleUrls, shim, suffix);
}

compileStylesheetCodeGen(moduleId: string, cssText: string): SourceModule[] {
var styleWithImports = resolveStyleUrls(this._urlResolver, moduleId, cssText);
compileStylesheetCodeGen(stylesheetUrl: string, cssText: string): SourceModule[] {
var styleWithImports = resolveStyleUrls(this._urlResolver, stylesheetUrl, cssText);
return [
this._styleModule(moduleId, false, this._styleCodeGen([styleWithImports.style],
styleWithImports.styleUrls, false, '')),
this._styleModule(moduleId, true, this._styleCodeGen([styleWithImports.style],
styleWithImports.styleUrls, true, ''))
this._styleModule(
stylesheetUrl, false,
this._styleCodeGen([styleWithImports.style], styleWithImports.styleUrls, false, '')),
this._styleModule(
stylesheetUrl, true,
this._styleCodeGen([styleWithImports.style], styleWithImports.styleUrls, true, ''))
];
}

Expand Down Expand Up @@ -96,28 +99,28 @@ export class StyleCompiler {
expressionSource +=
`[${plainStyles.map( plainStyle => escapeSingleQuoteString(this._shimIfNeeded(plainStyle, shim)) ).join(',')}]`;
for (var i = 0; i < absUrls.length; i++) {
var moduleId = this._shimModuleIdIfNeeded(absUrls[i], shim);
expressionSource += codeGenConcatArray(`${moduleRef(moduleId)}STYLES`);
var moduleUrl = this._createModuleUrl(absUrls[i], shim);
expressionSource += codeGenConcatArray(`${moduleRef(moduleUrl)}STYLES`);
}
expressionSource += `)${suffix}`;
return new SourceExpression([], expressionSource);
}

private _styleModule(moduleId: string, shim: boolean,
private _styleModule(stylesheetUrl: string, shim: boolean,
expression: SourceExpression): SourceModule {
var moduleSource = `
${expression.declarations.join('\n')}
${codeGenExportVariable('STYLES')}${expression.expression};
`;
return new SourceModule(this._shimModuleIdIfNeeded(moduleId, shim), moduleSource);
return new SourceModule(this._createModuleUrl(stylesheetUrl, shim), moduleSource);
}

private _shimIfNeeded(style: string, shim: boolean): string {
return shim ? this._shadowCss.shimCssText(style, CONTENT_ATTR, HOST_ATTR) : style;
}

private _shimModuleIdIfNeeded(moduleId: string, shim: boolean): string {
return shim ? `${moduleId}.shim` : moduleId;
private _createModuleUrl(stylesheetUrl: string, shim: boolean): string {
return shim ? `${stylesheetUrl}.shim${MODULE_SUFFIX}` : `${stylesheetUrl}${MODULE_SUFFIX}`;
}
}

Expand Down

0 comments on commit 681f69c

Please sign in to comment.