chore(compiler): refactoring for offline compiler cli

- pass a baseUrl for asset resolution from static symbols
- fixes in StaticReflector to work with a path-aware host

see #7483
This commit is contained in:
Alex Eagle 2016-04-28 21:54:02 -07:00
parent 8bf6ef6544
commit c493d88405
11 changed files with 357 additions and 280 deletions

View File

@ -468,13 +468,16 @@ export class CompileTemplateMetadata {
styles: string[]; styles: string[];
styleUrls: string[]; styleUrls: string[];
ngContentSelectors: string[]; ngContentSelectors: string[];
constructor({encapsulation, template, templateUrl, styles, styleUrls, ngContentSelectors}: { baseUrl: string;
constructor({encapsulation, template, templateUrl, styles, styleUrls, ngContentSelectors,
baseUrl}: {
encapsulation?: ViewEncapsulation, encapsulation?: ViewEncapsulation,
template?: string, template?: string,
templateUrl?: string, templateUrl?: string,
styles?: string[], styles?: string[],
styleUrls?: string[], styleUrls?: string[],
ngContentSelectors?: string[] ngContentSelectors?: string[],
baseUrl?: string
} = {}) { } = {}) {
this.encapsulation = isPresent(encapsulation) ? encapsulation : ViewEncapsulation.Emulated; this.encapsulation = isPresent(encapsulation) ? encapsulation : ViewEncapsulation.Emulated;
this.template = template; this.template = template;
@ -482,6 +485,7 @@ export class CompileTemplateMetadata {
this.styles = isPresent(styles) ? styles : []; this.styles = isPresent(styles) ? styles : [];
this.styleUrls = isPresent(styleUrls) ? styleUrls : []; this.styleUrls = isPresent(styleUrls) ? styleUrls : [];
this.ngContentSelectors = isPresent(ngContentSelectors) ? ngContentSelectors : []; this.ngContentSelectors = isPresent(ngContentSelectors) ? ngContentSelectors : [];
this.baseUrl = baseUrl;
} }
static fromJson(data: {[key: string]: any}): CompileTemplateMetadata { static fromJson(data: {[key: string]: any}): CompileTemplateMetadata {
@ -493,7 +497,8 @@ export class CompileTemplateMetadata {
templateUrl: data['templateUrl'], templateUrl: data['templateUrl'],
styles: data['styles'], styles: data['styles'],
styleUrls: data['styleUrls'], styleUrls: data['styleUrls'],
ngContentSelectors: data['ngContentSelectors'] ngContentSelectors: data['ngContentSelectors'],
baseUrl: data['baseUrl']
}); });
} }
@ -505,7 +510,8 @@ export class CompileTemplateMetadata {
'templateUrl': this.templateUrl, 'templateUrl': this.templateUrl,
'styles': this.styles, 'styles': this.styles,
'styleUrls': this.styleUrls, 'styleUrls': this.styleUrls,
'ngContentSelectors': this.ngContentSelectors 'ngContentSelectors': this.ngContentSelectors,
'baseUrl': this.baseUrl
}; };
} }
} }

View File

@ -66,9 +66,9 @@ export class DirectiveNormalizer {
template: CompileTemplateMetadata): Promise<CompileTemplateMetadata> { template: CompileTemplateMetadata): Promise<CompileTemplateMetadata> {
if (isPresent(template.template)) { if (isPresent(template.template)) {
return PromiseWrapper.resolve(this.normalizeLoadedTemplate( return PromiseWrapper.resolve(this.normalizeLoadedTemplate(
directiveType, template, template.template, directiveType.moduleUrl)); directiveType, template, template.template, template.baseUrl));
} else if (isPresent(template.templateUrl)) { } else if (isPresent(template.templateUrl)) {
var sourceAbsUrl = this._urlResolver.resolve(directiveType.moduleUrl, template.templateUrl); var sourceAbsUrl = this._urlResolver.resolve(template.baseUrl, template.templateUrl);
return this._xhr.get(sourceAbsUrl) return this._xhr.get(sourceAbsUrl)
.then(templateContent => this.normalizeLoadedTemplate(directiveType, template, .then(templateContent => this.normalizeLoadedTemplate(directiveType, template,
templateContent, sourceAbsUrl)); templateContent, sourceAbsUrl));
@ -93,7 +93,7 @@ export class DirectiveNormalizer {
visitor.styleUrls.filter(isStyleUrlResolvable) visitor.styleUrls.filter(isStyleUrlResolvable)
.map(url => this._urlResolver.resolve(templateAbsUrl, url)) .map(url => this._urlResolver.resolve(templateAbsUrl, url))
.concat(templateMeta.styleUrls.filter(isStyleUrlResolvable) .concat(templateMeta.styleUrls.filter(isStyleUrlResolvable)
.map(url => this._urlResolver.resolve(directiveType.moduleUrl, url))); .map(url => this._urlResolver.resolve(templateMeta.baseUrl, url)));
var allResolvedStyles = allStyles.map(style => { var allResolvedStyles = allStyles.map(style => {
var styleWithImports = extractStyleUrls(this._urlResolver, templateAbsUrl, style); var styleWithImports = extractStyleUrls(this._urlResolver, templateAbsUrl, style);

View File

@ -76,7 +76,6 @@ export class CompileMetadataResolver {
var meta = this._directiveCache.get(directiveType); var meta = this._directiveCache.get(directiveType);
if (isBlank(meta)) { if (isBlank(meta)) {
var dirMeta = this._directiveResolver.resolve(directiveType); var dirMeta = this._directiveResolver.resolve(directiveType);
var moduleUrl = staticTypeModuleUrl(directiveType);
var templateMeta = null; var templateMeta = null;
var changeDetectionStrategy = null; var changeDetectionStrategy = null;
var viewProviders = []; var viewProviders = [];
@ -84,7 +83,6 @@ export class CompileMetadataResolver {
if (dirMeta instanceof md.ComponentMetadata) { if (dirMeta instanceof md.ComponentMetadata) {
assertArrayOfStrings('styles', dirMeta.styles); assertArrayOfStrings('styles', dirMeta.styles);
var cmpMeta = <md.ComponentMetadata>dirMeta; var cmpMeta = <md.ComponentMetadata>dirMeta;
moduleUrl = calcModuleUrl(this._reflector, directiveType, cmpMeta);
var viewMeta = this._viewResolver.resolve(directiveType); var viewMeta = this._viewResolver.resolve(directiveType);
assertArrayOfStrings('styles', viewMeta.styles); assertArrayOfStrings('styles', viewMeta.styles);
templateMeta = new cpl.CompileTemplateMetadata({ templateMeta = new cpl.CompileTemplateMetadata({
@ -92,7 +90,8 @@ export class CompileMetadataResolver {
template: viewMeta.template, template: viewMeta.template,
templateUrl: viewMeta.templateUrl, templateUrl: viewMeta.templateUrl,
styles: viewMeta.styles, styles: viewMeta.styles,
styleUrls: viewMeta.styleUrls styleUrls: viewMeta.styleUrls,
baseUrl: calcTemplateBaseUrl(this._reflector, directiveType, cmpMeta)
}); });
changeDetectionStrategy = cmpMeta.changeDetection; changeDetectionStrategy = cmpMeta.changeDetection;
if (isPresent(dirMeta.viewProviders)) { if (isPresent(dirMeta.viewProviders)) {
@ -114,7 +113,7 @@ export class CompileMetadataResolver {
selector: dirMeta.selector, selector: dirMeta.selector,
exportAs: dirMeta.exportAs, exportAs: dirMeta.exportAs,
isComponent: isPresent(templateMeta), isComponent: isPresent(templateMeta),
type: this.getTypeMetadata(directiveType, moduleUrl), type: this.getTypeMetadata(directiveType, staticTypeModuleUrl(directiveType)),
template: templateMeta, template: templateMeta,
changeDetection: changeDetectionStrategy, changeDetection: changeDetectionStrategy,
inputs: dirMeta.inputs, inputs: dirMeta.inputs,
@ -399,14 +398,19 @@ function staticTypeModuleUrl(value: any): string {
return isStaticType(value) ? value['moduleId'] : null; return isStaticType(value) ? value['moduleId'] : null;
} }
function calcModuleUrl(reflector: ReflectorReader, type: Type,
function calcTemplateBaseUrl(reflector: ReflectorReader, type: any,
cmpMetadata: md.ComponentMetadata): string { cmpMetadata: md.ComponentMetadata): string {
if (isStaticType(type)) {
return type['filePath'];
}
if (isPresent(cmpMetadata.moduleId)) {
var moduleId = cmpMetadata.moduleId; var moduleId = cmpMetadata.moduleId;
if (isPresent(moduleId)) {
var scheme = getUrlScheme(moduleId); var scheme = getUrlScheme(moduleId);
return isPresent(scheme) && scheme.length > 0 ? moduleId : return isPresent(scheme) && scheme.length > 0 ? moduleId :
`package:${moduleId}${MODULE_SUFFIX}`; `package:${moduleId}${MODULE_SUFFIX}`;
} else { }
return reflector.importUri(type); return reflector.importUri(type);
} }
}

View File

@ -19,7 +19,6 @@ import {
HostListenerMetadata, HostListenerMetadata,
OutputMetadata, OutputMetadata,
PipeMetadata, PipeMetadata,
ViewMetadata,
ViewChildMetadata, ViewChildMetadata,
ViewChildrenMetadata, ViewChildrenMetadata,
ViewQueryMetadata, ViewQueryMetadata,
@ -37,6 +36,10 @@ import {
InjectMetadata InjectMetadata
} from "angular2/src/core/di/metadata"; } from "angular2/src/core/di/metadata";
export class ModuleContext {
constructor(public moduleId: string, public filePath: string) {}
}
/** /**
* The host of the static resolver is expected to be able to provide module metadata in the form of * The host of the static resolver is expected to be able to provide module metadata in the form of
* ModuleMetadata. Angular 2 CLI will produce this metadata for a module whenever a .d.ts files is * ModuleMetadata. Angular 2 CLI will produce this metadata for a module whenever a .d.ts files is
@ -53,14 +56,13 @@ export interface StaticReflectorHost {
getMetadataFor(modulePath: string): {[key: string]: any}; getMetadataFor(modulePath: string): {[key: string]: any};
/** /**
* Resolve a module from an import statement form to an absolute path. * Resolve a symbol from an import statement form, to the file where it is declared.
* @param moduleName the location imported from * @param module the location imported from
* @param containingFile for relative imports, the path of the file containing the import * @param containingFile for relative imports, the path of the file containing the import
*/ */
resolveModule(moduleName: string, containingFile?: string): string; findDeclaration(modulePath: string, symbolName: string, containingFile?: string): StaticSymbol;
findDeclaration(modulePath: string, getStaticSymbol(moduleId: string, declarationFile: string, name: string): StaticSymbol;
symbolName: string): {declarationPath: string, declaredName: string};
} }
/** /**
@ -68,8 +70,8 @@ export interface StaticReflectorHost {
* *
* This token is unique for a moduleId and name and can be used as a hash table key. * This token is unique for a moduleId and name and can be used as a hash table key.
*/ */
export class StaticType { export class StaticSymbol {
constructor(public moduleId: string, public name: string) {} constructor(public moduleId: string, public filePath: string, public name: string) {}
} }
/** /**
@ -77,40 +79,23 @@ export class StaticType {
* templates statically. * templates statically.
*/ */
export class StaticReflector implements ReflectorReader { export class StaticReflector implements ReflectorReader {
private typeCache = new Map<string, StaticType>(); private annotationCache = new Map<StaticSymbol, any[]>();
private annotationCache = new Map<StaticType, any[]>(); private propertyCache = new Map<StaticSymbol, {[key: string]: any}>();
private propertyCache = new Map<StaticType, {[key: string]: any}>(); private parameterCache = new Map<StaticSymbol, any[]>();
private parameterCache = new Map<StaticType, any[]>();
private metadataCache = new Map<string, {[key: string]: any}>(); private metadataCache = new Map<string, {[key: string]: any}>();
private conversionMap = new Map<StaticType, (moduleContext: string, args: any[]) => any>(); private conversionMap =
new Map<StaticSymbol, (moduleContext: ModuleContext, args: any[]) => any>();
constructor(private host: StaticReflectorHost) { this.initializeConversionMap(); } constructor(private host: StaticReflectorHost) { this.initializeConversionMap(); }
importUri(typeOrFunc: any): string { return (<StaticType>typeOrFunc).moduleId; } importUri(typeOrFunc: any): string { return (<StaticSymbol>typeOrFunc).filePath; }
/** public annotations(type: StaticSymbol): any[] {
* getStaticType produces a Type whose metadata is known but whose implementation is not loaded.
* All types passed to the StaticResolver should be pseudo-types returned by this method.
*
* @param moduleId the module identifier as an absolute path.
* @param name the name of the type.
*/
public getStaticType(moduleId: string, name: string): StaticType {
let key = `"${moduleId}".${name}`;
let result = this.typeCache.get(key);
if (!isPresent(result)) {
result = new StaticType(moduleId, name);
this.typeCache.set(key, result);
}
return result;
}
public annotations(type: StaticType): any[] {
let annotations = this.annotationCache.get(type); let annotations = this.annotationCache.get(type);
if (!isPresent(annotations)) { if (!isPresent(annotations)) {
let classMetadata = this.getTypeMetadata(type); let classMetadata = this.getTypeMetadata(type);
if (isPresent(classMetadata['decorators'])) { if (isPresent(classMetadata['decorators'])) {
annotations = this.simplify(type.moduleId, classMetadata['decorators'], false); annotations = this.simplify(type, classMetadata['decorators'], false);
} else { } else {
annotations = []; annotations = [];
} }
@ -119,7 +104,7 @@ export class StaticReflector implements ReflectorReader {
return annotations; return annotations;
} }
public propMetadata(type: StaticType): {[key: string]: any} { public propMetadata(type: StaticSymbol): {[key: string]: any} {
let propMetadata = this.propertyCache.get(type); let propMetadata = this.propertyCache.get(type);
if (!isPresent(propMetadata)) { if (!isPresent(propMetadata)) {
let classMetadata = this.getTypeMetadata(type); let classMetadata = this.getTypeMetadata(type);
@ -127,7 +112,7 @@ export class StaticReflector implements ReflectorReader {
propMetadata = mapStringMap(members, (propData, propName) => { propMetadata = mapStringMap(members, (propData, propName) => {
let prop = (<any[]>propData).find(a => a['__symbolic'] == 'property'); let prop = (<any[]>propData).find(a => a['__symbolic'] == 'property');
if (isPresent(prop) && isPresent(prop['decorators'])) { if (isPresent(prop) && isPresent(prop['decorators'])) {
return this.simplify(type.moduleId, prop['decorators'], false); return this.simplify(type, prop['decorators'], false);
} else { } else {
return []; return [];
} }
@ -137,7 +122,7 @@ export class StaticReflector implements ReflectorReader {
return propMetadata; return propMetadata;
} }
public parameters(type: StaticType): any[] { public parameters(type: StaticSymbol): any[] {
let parameters = this.parameterCache.get(type); let parameters = this.parameterCache.get(type);
if (!isPresent(parameters)) { if (!isPresent(parameters)) {
let classMetadata = this.getTypeMetadata(type); let classMetadata = this.getTypeMetadata(type);
@ -145,9 +130,8 @@ export class StaticReflector implements ReflectorReader {
let ctorData = isPresent(members) ? members['__ctor__'] : null; let ctorData = isPresent(members) ? members['__ctor__'] : null;
if (isPresent(ctorData)) { if (isPresent(ctorData)) {
let ctor = (<any[]>ctorData).find(a => a['__symbolic'] == 'constructor'); let ctor = (<any[]>ctorData).find(a => a['__symbolic'] == 'constructor');
let parameterTypes = <any[]>this.simplify(type.moduleId, ctor['parameters'], false); let parameterTypes = <any[]>this.simplify(type, ctor['parameters'], false);
let parameterDecorators = let parameterDecorators = <any[]>this.simplify(type, ctor['parameterDecorators'], false);
<any[]>this.simplify(type.moduleId, ctor['parameterDecorators'], false);
parameters = []; parameters = [];
ListWrapper.forEachWithIndex(parameterTypes, (paramType, index) => { ListWrapper.forEachWithIndex(parameterTypes, (paramType, index) => {
@ -170,9 +154,9 @@ export class StaticReflector implements ReflectorReader {
return parameters; return parameters;
} }
private registerDecoratorOrConstructor(type: StaticType, ctor: any, private registerDecoratorOrConstructor(type: StaticSymbol, ctor: any,
crossModuleProps: any[] = CONST_EXPR([])): void { crossModuleProps: any[] = CONST_EXPR([])): void {
this.conversionMap.set(type, (moduleContext: string, args: any[]) => { this.conversionMap.set(type, (moduleContext: ModuleContext, args: any[]) => {
let argValues = []; let argValues = [];
ListWrapper.forEachWithIndex(args, (arg, index) => { ListWrapper.forEachWithIndex(args, (arg, index) => {
let argValue; let argValue;
@ -190,62 +174,67 @@ export class StaticReflector implements ReflectorReader {
} }
private initializeConversionMap(): void { private initializeConversionMap(): void {
let coreDecorators = this.host.resolveModule('angular2/src/core/metadata'); let coreDecorators = 'angular2/src/core/metadata';
let diDecorators = this.host.resolveModule('angular2/src/core/di/decorators'); let diDecorators = 'angular2/src/core/di/decorators';
let diMetadata = this.host.resolveModule('angular2/src/core/di/metadata'); let diMetadata = 'angular2/src/core/di/metadata';
let provider = 'angular2/src/core/di/provider';
this.registerDecoratorOrConstructor(this.host.findDeclaration(provider, 'Provider'), Provider);
let provider = this.host.resolveModule('angular2/src/core/di/provider'); this.registerDecoratorOrConstructor(this.host.findDeclaration(diDecorators, 'Host'),
this.registerDecoratorOrConstructor(this.getStaticType(provider, 'Provider'), Provider); HostMetadata);
this.registerDecoratorOrConstructor(this.host.findDeclaration(diDecorators, 'Injectable'),
this.registerDecoratorOrConstructor(this.getStaticType(diDecorators, 'Host'), HostMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(diDecorators, 'Injectable'),
InjectableMetadata); InjectableMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(diDecorators, 'Self'), SelfMetadata); this.registerDecoratorOrConstructor(this.host.findDeclaration(diDecorators, 'Self'),
this.registerDecoratorOrConstructor(this.getStaticType(diDecorators, 'SkipSelf'), SelfMetadata);
this.registerDecoratorOrConstructor(this.host.findDeclaration(diDecorators, 'SkipSelf'),
SkipSelfMetadata); SkipSelfMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(diDecorators, 'Inject'), InjectMetadata); this.registerDecoratorOrConstructor(this.host.findDeclaration(diDecorators, 'Inject'),
this.registerDecoratorOrConstructor(this.getStaticType(diDecorators, 'Optional'), InjectMetadata);
this.registerDecoratorOrConstructor(this.host.findDeclaration(diDecorators, 'Optional'),
OptionalMetadata); OptionalMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'Attribute'), this.registerDecoratorOrConstructor(this.host.findDeclaration(coreDecorators, 'Attribute'),
AttributeMetadata); AttributeMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'Query'), QueryMetadata); this.registerDecoratorOrConstructor(this.host.findDeclaration(coreDecorators, 'Query'),
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'ViewQuery'), QueryMetadata);
this.registerDecoratorOrConstructor(this.host.findDeclaration(coreDecorators, 'ViewQuery'),
ViewQueryMetadata); ViewQueryMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'ContentChild'), this.registerDecoratorOrConstructor(this.host.findDeclaration(coreDecorators, 'ContentChild'),
ContentChildMetadata); ContentChildMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'ContentChildren'), this.registerDecoratorOrConstructor(
ContentChildrenMetadata); this.host.findDeclaration(coreDecorators, 'ContentChildren'), ContentChildrenMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'ViewChild'), this.registerDecoratorOrConstructor(this.host.findDeclaration(coreDecorators, 'ViewChild'),
ViewChildMetadata); ViewChildMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'ViewChildren'), this.registerDecoratorOrConstructor(this.host.findDeclaration(coreDecorators, 'ViewChildren'),
ViewChildrenMetadata); ViewChildrenMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'Input'), InputMetadata); this.registerDecoratorOrConstructor(this.host.findDeclaration(coreDecorators, 'Input'),
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'Output'), InputMetadata);
this.registerDecoratorOrConstructor(this.host.findDeclaration(coreDecorators, 'Output'),
OutputMetadata); OutputMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'Pipe'), PipeMetadata); this.registerDecoratorOrConstructor(this.host.findDeclaration(coreDecorators, 'Pipe'),
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'HostBinding'), PipeMetadata);
this.registerDecoratorOrConstructor(this.host.findDeclaration(coreDecorators, 'HostBinding'),
HostBindingMetadata); HostBindingMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'HostListener'), this.registerDecoratorOrConstructor(this.host.findDeclaration(coreDecorators, 'HostListener'),
HostListenerMetadata); HostListenerMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'Directive'), this.registerDecoratorOrConstructor(this.host.findDeclaration(coreDecorators, 'Directive'),
DirectiveMetadata, ['bindings', 'providers']); DirectiveMetadata, ['bindings', 'providers']);
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'Component'), this.registerDecoratorOrConstructor(this.host.findDeclaration(coreDecorators, 'Component'),
ComponentMetadata, ComponentMetadata,
['bindings', 'providers', 'directives', 'pipes']); ['bindings', 'providers', 'directives', 'pipes']);
// Note: Some metadata classes can be used directly with Provider.deps. // Note: Some metadata classes can be used directly with Provider.deps.
this.registerDecoratorOrConstructor(this.getStaticType(diMetadata, 'HostMetadata'), this.registerDecoratorOrConstructor(this.host.findDeclaration(diMetadata, 'HostMetadata'),
HostMetadata); HostMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(diMetadata, 'SelfMetadata'), this.registerDecoratorOrConstructor(this.host.findDeclaration(diMetadata, 'SelfMetadata'),
SelfMetadata); SelfMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(diMetadata, 'SkipSelfMetadata'), this.registerDecoratorOrConstructor(this.host.findDeclaration(diMetadata, 'SkipSelfMetadata'),
SkipSelfMetadata); SkipSelfMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(diMetadata, 'OptionalMetadata'), this.registerDecoratorOrConstructor(this.host.findDeclaration(diMetadata, 'OptionalMetadata'),
OptionalMetadata); OptionalMetadata);
} }
/** @internal */ /** @internal */
public simplify(moduleContext: string, value: any, crossModules: boolean): any { public simplify(moduleContext: ModuleContext, value: any, crossModules: boolean): any {
let _this = this; let _this = this;
function simplify(expression: any): any { function simplify(expression: any): any {
@ -261,6 +250,7 @@ export class StaticReflector implements ReflectorReader {
} }
if (isPresent(expression)) { if (isPresent(expression)) {
if (isPresent(expression['__symbolic'])) { if (isPresent(expression['__symbolic'])) {
let staticSymbol;
switch (expression['__symbolic']) { switch (expression['__symbolic']) {
case "binop": case "binop":
let left = simplify(expression['left']); let left = simplify(expression['left']);
@ -332,35 +322,34 @@ export class StaticReflector implements ReflectorReader {
if (isPresent(selectTarget) && isPrimitive(member)) return selectTarget[member]; if (isPresent(selectTarget) && isPrimitive(member)) return selectTarget[member];
return null; return null;
case "reference": case "reference":
let referenceModuleName;
let declarationPath = moduleContext;
let declaredName = expression['name'];
if (isPresent(expression['module'])) { if (isPresent(expression['module'])) {
referenceModuleName = _this.host.resolveModule(expression['module'], moduleContext); staticSymbol = _this.host.findDeclaration(expression['module'], expression['name'],
let decl = _this.host.findDeclaration(referenceModuleName, expression['name']); moduleContext.filePath);
declarationPath = decl['declarationPath']; } else {
declaredName = decl['declaredName']; staticSymbol = _this.host.getStaticSymbol(
moduleContext.moduleId, moduleContext.filePath, expression['name']);
} }
let result; let result;
if (crossModules || isBlank(expression['module'])) { if (crossModules || isBlank(expression['module'])) {
let moduleMetadata = _this.getModuleMetadata(declarationPath); let moduleMetadata = _this.getModuleMetadata(staticSymbol.filePath);
let declarationValue = moduleMetadata['metadata'][declaredName]; let declarationValue = moduleMetadata['metadata'][staticSymbol.name];
if (isClassMetadata(declarationValue)) { if (isClassMetadata(declarationValue)) {
result = _this.getStaticType(declarationPath, declaredName); result = staticSymbol;
} else { } else {
result = _this.simplify(declarationPath, declarationValue, crossModules); const newModuleContext =
new ModuleContext(staticSymbol.moduleId, staticSymbol.filePath);
result = _this.simplify(newModuleContext, declarationValue, crossModules);
} }
} else { } else {
result = _this.getStaticType(declarationPath, declaredName); result = staticSymbol;
} }
return result; return result;
case "new": case "new":
case "call": case "call":
let target = expression['expression']; let target = expression['expression'];
let moduleId = _this.host.resolveModule(target['module'], moduleContext); staticSymbol = _this.host.findDeclaration(target['module'], target['name'],
let decl = _this.host.findDeclaration(moduleId, target['name']); moduleContext.filePath);
let staticType = _this.getStaticType(decl['declarationPath'], decl['declaredName']); let converter = _this.conversionMap.get(staticSymbol);
let converter = _this.conversionMap.get(staticType);
let args = expression['arguments']; let args = expression['arguments'];
if (isBlank(args)) { if (isBlank(args)) {
args = []; args = [];
@ -392,8 +381,11 @@ export class StaticReflector implements ReflectorReader {
return moduleMetadata; return moduleMetadata;
} }
private getTypeMetadata(type: StaticType): {[key: string]: any} { private getTypeMetadata(type: StaticSymbol): {[key: string]: any} {
let moduleMetadata = this.getModuleMetadata(type.moduleId); if (!(type instanceof StaticSymbol)) {
throw new Error('not static type');
}
let moduleMetadata = this.getModuleMetadata(type.filePath);
let result = moduleMetadata['metadata'][type.name]; let result = moduleMetadata['metadata'][type.name];
if (!isPresent(result)) { if (!isPresent(result)) {
result = {__symbolic: "class"}; result = {__symbolic: "class"};

View File

@ -87,7 +87,8 @@ export class CompileEventListener {
[ [
new o.ReturnStatement( new o.ReturnStatement(
o.THIS_EXPR.callMethod(this._methodName, [EventHandlerVars.event])) o.THIS_EXPR.callMethod(this._methodName, [EventHandlerVars.event]))
], o.BOOL_TYPE) ],
o.BOOL_TYPE)
]); ]);
if (isPresent(this.eventTarget)) { if (isPresent(this.eventTarget)) {
listenExpr = ViewProperties.renderer.callMethod( listenExpr = ViewProperties.renderer.callMethod(

View File

@ -63,7 +63,8 @@ export function main() {
templateUrl: 'someTemplateUrl', templateUrl: 'someTemplateUrl',
styles: ['someStyle'], styles: ['someStyle'],
styleUrls: ['someStyleUrl'], styleUrls: ['someStyleUrl'],
ngContentSelectors: ['*'] ngContentSelectors: ['*'],
baseUrl: 'someBaseUrl'
}); });
fullDirectiveMeta = CompileDirectiveMetadata.create({ fullDirectiveMeta = CompileDirectiveMetadata.create({
selector: 'someSelector', selector: 'someSelector',

View File

@ -24,15 +24,10 @@ import {TEST_PROVIDERS} from './test_bindings';
export function main() { export function main() {
describe('DirectiveNormalizer', () => { describe('DirectiveNormalizer', () => {
var dirType: CompileTypeMetadata; var dirType: CompileTypeMetadata;
var dirTypeWithHttpUrl: CompileTypeMetadata;
beforeEachProviders(() => TEST_PROVIDERS); beforeEachProviders(() => TEST_PROVIDERS);
beforeEach(() => { beforeEach(() => { dirType = new CompileTypeMetadata({name: 'SomeComp'}); });
dirType = new CompileTypeMetadata({moduleUrl: 'package:some/module/a.js', name: 'SomeComp'});
dirTypeWithHttpUrl =
new CompileTypeMetadata({moduleUrl: 'http://some/module/a.js', name: 'SomeComp'});
});
describe('loadTemplate', () => { describe('loadTemplate', () => {
describe('inline template', () => { describe('inline template', () => {
@ -44,7 +39,8 @@ export function main() {
template: 'a', template: 'a',
templateUrl: null, templateUrl: null,
styles: [], styles: [],
styleUrls: ['test.css'] styleUrls: ['test.css'],
baseUrl: 'package:some/module/a.js'
})) }))
.then((template: CompileTemplateMetadata) => { .then((template: CompileTemplateMetadata) => {
expect(template.template).toEqual('a'); expect(template.template).toEqual('a');
@ -53,7 +49,7 @@ export function main() {
}); });
})); }));
it('should resolve styles on the annotation against the moduleUrl', it('should resolve styles on the annotation against the baseUrl',
inject([AsyncTestCompleter, DirectiveNormalizer], inject([AsyncTestCompleter, DirectiveNormalizer],
(async, normalizer: DirectiveNormalizer) => { (async, normalizer: DirectiveNormalizer) => {
normalizer.normalizeTemplate(dirType, new CompileTemplateMetadata({ normalizer.normalizeTemplate(dirType, new CompileTemplateMetadata({
@ -61,7 +57,8 @@ export function main() {
template: '', template: '',
templateUrl: null, templateUrl: null,
styles: [], styles: [],
styleUrls: ['test.css'] styleUrls: ['test.css'],
baseUrl: 'package:some/module/a.js'
})) }))
.then((template: CompileTemplateMetadata) => { .then((template: CompileTemplateMetadata) => {
expect(template.styleUrls).toEqual(['package:some/module/test.css']); expect(template.styleUrls).toEqual(['package:some/module/test.css']);
@ -69,7 +66,7 @@ export function main() {
}); });
})); }));
it('should resolve styles in the template against the moduleUrl', it('should resolve styles in the template against the baseUrl',
inject([AsyncTestCompleter, DirectiveNormalizer], inject([AsyncTestCompleter, DirectiveNormalizer],
(async, normalizer: DirectiveNormalizer) => { (async, normalizer: DirectiveNormalizer) => {
normalizer.normalizeTemplate(dirType, new CompileTemplateMetadata({ normalizer.normalizeTemplate(dirType, new CompileTemplateMetadata({
@ -77,7 +74,8 @@ export function main() {
template: '<style>@import test.css</style>', template: '<style>@import test.css</style>',
templateUrl: null, templateUrl: null,
styles: [], styles: [],
styleUrls: [] styleUrls: [],
baseUrl: 'package:some/module/a.js'
})) }))
.then((template: CompileTemplateMetadata) => { .then((template: CompileTemplateMetadata) => {
expect(template.styleUrls).toEqual(['package:some/module/test.css']); expect(template.styleUrls).toEqual(['package:some/module/test.css']);
@ -88,7 +86,7 @@ export function main() {
describe('templateUrl', () => { describe('templateUrl', () => {
it('should load a template from a url that is resolved against moduleUrl', it('should load a template from a url that is resolved against baseUrl',
inject([AsyncTestCompleter, DirectiveNormalizer, XHR], inject([AsyncTestCompleter, DirectiveNormalizer, XHR],
(async, normalizer: DirectiveNormalizer, xhr: MockXHR) => { (async, normalizer: DirectiveNormalizer, xhr: MockXHR) => {
xhr.expect('package:some/module/sometplurl.html', 'a'); xhr.expect('package:some/module/sometplurl.html', 'a');
@ -97,7 +95,8 @@ export function main() {
template: null, template: null,
templateUrl: 'sometplurl.html', templateUrl: 'sometplurl.html',
styles: [], styles: [],
styleUrls: ['test.css'] styleUrls: ['test.css'],
baseUrl: 'package:some/module/a.js'
})) }))
.then((template: CompileTemplateMetadata) => { .then((template: CompileTemplateMetadata) => {
expect(template.template).toEqual('a'); expect(template.template).toEqual('a');
@ -108,7 +107,7 @@ export function main() {
xhr.flush(); xhr.flush();
})); }));
it('should resolve styles on the annotation against the moduleUrl', it('should resolve styles on the annotation against the baseUrl',
inject([AsyncTestCompleter, DirectiveNormalizer, XHR], inject([AsyncTestCompleter, DirectiveNormalizer, XHR],
(async, normalizer: DirectiveNormalizer, xhr: MockXHR) => { (async, normalizer: DirectiveNormalizer, xhr: MockXHR) => {
xhr.expect('package:some/module/tpl/sometplurl.html', ''); xhr.expect('package:some/module/tpl/sometplurl.html', '');
@ -117,7 +116,8 @@ export function main() {
template: null, template: null,
templateUrl: 'tpl/sometplurl.html', templateUrl: 'tpl/sometplurl.html',
styles: [], styles: [],
styleUrls: ['test.css'] styleUrls: ['test.css'],
baseUrl: 'package:some/module/a.js'
})) }))
.then((template: CompileTemplateMetadata) => { .then((template: CompileTemplateMetadata) => {
expect(template.styleUrls).toEqual(['package:some/module/test.css']); expect(template.styleUrls).toEqual(['package:some/module/test.css']);
@ -136,7 +136,8 @@ export function main() {
template: null, template: null,
templateUrl: 'tpl/sometplurl.html', templateUrl: 'tpl/sometplurl.html',
styles: [], styles: [],
styleUrls: [] styleUrls: [],
baseUrl: 'package:some/module/a.js'
})) }))
.then((template: CompileTemplateMetadata) => { .then((template: CompileTemplateMetadata) => {
expect(template.styleUrls).toEqual(['package:some/module/tpl/test.css']); expect(template.styleUrls).toEqual(['package:some/module/tpl/test.css']);
@ -162,36 +163,50 @@ export function main() {
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
var viewEncapsulation = ViewEncapsulation.Native; var viewEncapsulation = ViewEncapsulation.Native;
var template = normalizer.normalizeLoadedTemplate( var template = normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
dirType, new CompileTemplateMetadata( encapsulation: viewEncapsulation,
{encapsulation: viewEncapsulation, styles: [], styleUrls: []}), styles: [],
styleUrls: [],
baseUrl: 'package:some/module/a.js'
}),
'', 'package:some/module/'); '', 'package:some/module/');
expect(template.encapsulation).toBe(viewEncapsulation); expect(template.encapsulation).toBe(viewEncapsulation);
})); }));
it('should keep the template as html', it('should keep the template as html',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
var template = normalizer.normalizeLoadedTemplate( var template = normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
dirType, encapsulation: null,
new CompileTemplateMetadata({encapsulation: null, styles: [], styleUrls: []}), 'a', styles: [],
'package:some/module/'); styleUrls: [],
baseUrl: 'package:some/module/a.js'
}),
'a', 'package:some/module/');
expect(template.template).toEqual('a') expect(template.template).toEqual('a')
})); }));
it('should collect ngContent', it('should collect ngContent',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
var template = normalizer.normalizeLoadedTemplate( var template = normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
dirType, encapsulation: null,
new CompileTemplateMetadata({encapsulation: null, styles: [], styleUrls: []}), styles: [],
'<ng-content select="a"></ng-content>', 'package:some/module/'); styleUrls: [],
baseUrl: 'package:some/module/a.js'
}),
'<ng-content select="a"></ng-content>',
'package:some/module/');
expect(template.ngContentSelectors).toEqual(['a']); expect(template.ngContentSelectors).toEqual(['a']);
})); }));
it('should normalize ngContent wildcard selector', it('should normalize ngContent wildcard selector',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
var template = normalizer.normalizeLoadedTemplate( var template = normalizer.normalizeLoadedTemplate(
dirType, dirType, new CompileTemplateMetadata({
new CompileTemplateMetadata({encapsulation: null, styles: [], styleUrls: []}), encapsulation: null,
styles: [],
styleUrls: [],
baseUrl: 'package:some/module/a.js'
}),
'<ng-content></ng-content><ng-content select></ng-content><ng-content select="*"></ng-content>', '<ng-content></ng-content><ng-content select></ng-content><ng-content select="*"></ng-content>',
'package:some/module/'); 'package:some/module/');
expect(template.ngContentSelectors).toEqual(['*', '*', '*']); expect(template.ngContentSelectors).toEqual(['*', '*', '*']);
@ -199,63 +214,90 @@ export function main() {
it('should collect top level styles in the template', it('should collect top level styles in the template',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
var template = normalizer.normalizeLoadedTemplate( var template =
dirType, normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
new CompileTemplateMetadata({encapsulation: null, styles: [], styleUrls: []}), encapsulation: null,
styles: [],
styleUrls: [],
baseUrl: 'package:some/module/a.js'
}),
'<style>a</style>', 'package:some/module/'); '<style>a</style>', 'package:some/module/');
expect(template.styles).toEqual(['a']); expect(template.styles).toEqual(['a']);
})); }));
it('should collect styles inside in elements', it('should collect styles inside in elements',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
var template = normalizer.normalizeLoadedTemplate( var template = normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
dirType, encapsulation: null,
new CompileTemplateMetadata({encapsulation: null, styles: [], styleUrls: []}), styles: [],
'<div><style>a</style></div>', 'package:some/module/'); styleUrls: [],
baseUrl: 'package:some/module/a.js'
}),
'<div><style>a</style></div>',
'package:some/module/');
expect(template.styles).toEqual(['a']); expect(template.styles).toEqual(['a']);
})); }));
it('should collect styleUrls in the template', it('should collect styleUrls in the template',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
var template = normalizer.normalizeLoadedTemplate( var template = normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
dirType, encapsulation: null,
new CompileTemplateMetadata({encapsulation: null, styles: [], styleUrls: []}), styles: [],
'<link rel="stylesheet" href="aUrl">', 'package:some/module/'); styleUrls: [],
baseUrl: 'package:some/module/a.js'
}),
'<link rel="stylesheet" href="aUrl">',
'package:some/module/');
expect(template.styleUrls).toEqual(['package:some/module/aUrl']); expect(template.styleUrls).toEqual(['package:some/module/aUrl']);
})); }));
it('should collect styleUrls in elements', it('should collect styleUrls in elements',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
var template = normalizer.normalizeLoadedTemplate( var template = normalizer.normalizeLoadedTemplate(
dirType, dirType, new CompileTemplateMetadata({
new CompileTemplateMetadata({encapsulation: null, styles: [], styleUrls: []}), encapsulation: null,
styles: [],
styleUrls: [],
baseUrl: 'package:some/module/a.js'
}),
'<div><link rel="stylesheet" href="aUrl"></div>', 'package:some/module/'); '<div><link rel="stylesheet" href="aUrl"></div>', 'package:some/module/');
expect(template.styleUrls).toEqual(['package:some/module/aUrl']); expect(template.styleUrls).toEqual(['package:some/module/aUrl']);
})); }));
it('should ignore link elements with non stylesheet rel attribute', it('should ignore link elements with non stylesheet rel attribute',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
var template = normalizer.normalizeLoadedTemplate( var template = normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
dirType, encapsulation: null,
new CompileTemplateMetadata({encapsulation: null, styles: [], styleUrls: []}), styles: [],
'<link href="b" rel="a">', 'package:some/module/'); styleUrls: [],
baseUrl: 'package:some/module/a.js'
}),
'<link href="b" rel="a">',
'package:some/module/');
expect(template.styleUrls).toEqual([]); expect(template.styleUrls).toEqual([]);
})); }));
it('should ignore link elements with absolute urls but non package: scheme', it('should ignore link elements with absolute urls but non package: scheme',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
var template = normalizer.normalizeLoadedTemplate( var template = normalizer.normalizeLoadedTemplate(
dirType, dirType, new CompileTemplateMetadata({
new CompileTemplateMetadata({encapsulation: null, styles: [], styleUrls: []}), encapsulation: null,
styles: [],
styleUrls: [],
baseUrl: 'package:some/module/a.js'
}),
'<link href="http://some/external.css" rel="stylesheet">', 'package:some/module/'); '<link href="http://some/external.css" rel="stylesheet">', 'package:some/module/');
expect(template.styleUrls).toEqual([]); expect(template.styleUrls).toEqual([]);
})); }));
it('should extract @import style urls into styleAbsUrl', it('should extract @import style urls into styleAbsUrl',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
var template = normalizer.normalizeLoadedTemplate( var template = normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
dirType, new CompileTemplateMetadata( encapsulation: null,
{encapsulation: null, styles: ['@import "test.css";'], styleUrls: []}), styles: ['@import "test.css";'],
styleUrls: [],
baseUrl: 'package:some/module/a.js'
}),
'', 'package:some/module/id'); '', 'package:some/module/id');
expect(template.styles).toEqual(['']); expect(template.styles).toEqual(['']);
expect(template.styleUrls).toEqual(['package:some/module/test.css']); expect(template.styleUrls).toEqual(['package:some/module/test.css']);
@ -267,7 +309,8 @@ export function main() {
dirType, new CompileTemplateMetadata({ dirType, new CompileTemplateMetadata({
encapsulation: null, encapsulation: null,
styles: ['.foo{background-image: url(\'double.jpg\');'], styles: ['.foo{background-image: url(\'double.jpg\');'],
styleUrls: [] styleUrls: [],
baseUrl: 'package:some/module/a.js'
}), }),
'', 'package:some/module/id'); '', 'package:some/module/id');
expect(template.styles).toEqual(['.foo{background-image: url(\'double.jpg\');']); expect(template.styles).toEqual(['.foo{background-image: url(\'double.jpg\');']);
@ -275,9 +318,12 @@ export function main() {
it('should resolve relative style urls in styleUrls', it('should resolve relative style urls in styleUrls',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
var template = normalizer.normalizeLoadedTemplate( var template = normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
dirType, new CompileTemplateMetadata( encapsulation: null,
{encapsulation: null, styles: [], styleUrls: ['test.css']}), styles: [],
styleUrls: ['test.css'],
baseUrl: 'package:some/module/a.js'
}),
'', 'package:some/module/id'); '', 'package:some/module/id');
expect(template.styles).toEqual([]); expect(template.styles).toEqual([]);
expect(template.styleUrls).toEqual(['package:some/module/test.css']); expect(template.styleUrls).toEqual(['package:some/module/test.css']);
@ -285,9 +331,12 @@ export function main() {
it('should resolve relative style urls in styleUrls with http directive url', it('should resolve relative style urls in styleUrls with http directive url',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
var template = normalizer.normalizeLoadedTemplate( var template = normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
dirTypeWithHttpUrl, new CompileTemplateMetadata( encapsulation: null,
{encapsulation: null, styles: [], styleUrls: ['test.css']}), styles: [],
styleUrls: ['test.css'],
baseUrl: 'http://some/module/a.js'
}),
'', 'http://some/module/id'); '', 'http://some/module/id');
expect(template.styles).toEqual([]); expect(template.styles).toEqual([]);
expect(template.styleUrls).toEqual(['http://some/module/test.css']); expect(template.styleUrls).toEqual(['http://some/module/test.css']);
@ -295,9 +344,13 @@ export function main() {
it('should normalize ViewEncapsulation.Emulated to ViewEncapsulation.None if there are no styles nor stylesheets', it('should normalize ViewEncapsulation.Emulated to ViewEncapsulation.None if there are no styles nor stylesheets',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
var template = normalizer.normalizeLoadedTemplate( var template =
dirType, new CompileTemplateMetadata( normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
{encapsulation: ViewEncapsulation.Emulated, styles: [], styleUrls: []}), encapsulation: ViewEncapsulation.Emulated,
styles: [],
styleUrls: [],
baseUrl: 'package:some/module/a.js'
}),
'', 'package:some/module/id'); '', 'package:some/module/id');
expect(template.encapsulation).toEqual(ViewEncapsulation.None); expect(template.encapsulation).toEqual(ViewEncapsulation.None);
})); }));
@ -305,8 +358,12 @@ export function main() {
it('should ignore ng-content in elements with ngNonBindable', it('should ignore ng-content in elements with ngNonBindable',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
var template = normalizer.normalizeLoadedTemplate( var template = normalizer.normalizeLoadedTemplate(
dirType, dirType, new CompileTemplateMetadata({
new CompileTemplateMetadata({encapsulation: null, styles: [], styleUrls: []}), encapsulation: null,
styles: [],
styleUrls: [],
baseUrl: 'package:some/module/a.js'
}),
'<div ngNonBindable><ng-content select="a"></ng-content></div>', '<div ngNonBindable><ng-content select="a"></ng-content></div>',
'package:some/module/'); 'package:some/module/');
expect(template.ngContentSelectors).toEqual([]); expect(template.ngContentSelectors).toEqual([]);
@ -315,8 +372,12 @@ export function main() {
it('should still collect <style> in elements with ngNonBindable', it('should still collect <style> in elements with ngNonBindable',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
var template = normalizer.normalizeLoadedTemplate( var template = normalizer.normalizeLoadedTemplate(
dirType, dirType, new CompileTemplateMetadata({
new CompileTemplateMetadata({encapsulation: null, styles: [], styleUrls: []}), encapsulation: null,
styles: [],
styleUrls: [],
baseUrl: 'package:some/module/a.js'
}),
'<div ngNonBindable><style>div {color:red}</style></div>', 'package:some/module/'); '<div ngNonBindable><style>div {color:red}</style></div>', 'package:some/module/');
expect(template.styles).toEqual(['div {color:red}']); expect(template.styles).toEqual(['div {color:red}']);
})); }));

View File

@ -51,7 +51,6 @@ export function main() {
expect(meta.isComponent).toBe(true); expect(meta.isComponent).toBe(true);
expect(meta.type.runtime).toBe(ComponentWithEverything); expect(meta.type.runtime).toBe(ComponentWithEverything);
expect(meta.type.name).toEqual(stringify(ComponentWithEverything)); expect(meta.type.name).toEqual(stringify(ComponentWithEverything));
expect(meta.type.moduleUrl).toEqual(`package:someModuleId${MODULE_SUFFIX}`);
expect(meta.lifecycleHooks).toEqual(LIFECYCLE_HOOKS_VALUES); expect(meta.lifecycleHooks).toEqual(LIFECYCLE_HOOKS_VALUES);
expect(meta.changeDetection).toBe(ChangeDetectionStrategy.CheckAlways); expect(meta.changeDetection).toBe(ChangeDetectionStrategy.CheckAlways);
expect(meta.inputs).toEqual({'someProp': 'someProp'}); expect(meta.inputs).toEqual({'someProp': 'someProp'});
@ -64,12 +63,13 @@ export function main() {
expect(meta.template.styleUrls).toEqual(['someStyleUrl']); expect(meta.template.styleUrls).toEqual(['someStyleUrl']);
expect(meta.template.template).toEqual('someTemplate'); expect(meta.template.template).toEqual('someTemplate');
expect(meta.template.templateUrl).toEqual('someTemplateUrl'); expect(meta.template.templateUrl).toEqual('someTemplateUrl');
expect(meta.template.baseUrl).toEqual(`package:someModuleId${MODULE_SUFFIX}`);
})); }));
it('should use the moduleUrl from the reflector if none is given', it('should use the moduleUrl from the reflector if none is given',
inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => { inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
var value: string = var value: string =
resolver.getDirectiveMetadata(ComponentWithoutModuleId).type.moduleUrl; resolver.getDirectiveMetadata(ComponentWithoutModuleId).template.baseUrl;
var expectedEndValue = var expectedEndValue =
IS_DART ? 'test/compiler/metadata_resolver_spec.dart' : './ComponentWithoutModuleId'; IS_DART ? 'test/compiler/metadata_resolver_spec.dart' : './ComponentWithoutModuleId';
expect(value.endsWith(expectedEndValue)).toBe(true); expect(value.endsWith(expectedEndValue)).toBe(true);

View File

@ -39,7 +39,8 @@ export var compAMetadata = CompileDirectiveMetadata.create({
template: new CompileTemplateMetadata({ template: new CompileTemplateMetadata({
templateUrl: './offline_compiler_compa.html', templateUrl: './offline_compiler_compa.html',
styles: ['.redStyle { color: red; }'], styles: ['.redStyle { color: red; }'],
styleUrls: ['./offline_compiler_compa.css'] styleUrls: ['./offline_compiler_compa.css'],
baseUrl: THIS_MODULE_URL,
}) })
}); });

View File

@ -1,13 +1,19 @@
import {describe, it, iit, expect, ddescribe, beforeEach} from 'angular2/testing_internal'; import {describe, it, iit, expect, ddescribe, beforeEach} from 'angular2/testing_internal';
import {IS_DART} from 'angular2/src/facade/lang'; import {IS_DART, isBlank} from 'angular2/src/facade/lang';
import {ListWrapper} from 'angular2/src/facade/collection'; import {ListWrapper} from 'angular2/src/facade/collection';
import {StaticReflector, StaticReflectorHost} from 'angular2/src/compiler/static_reflector'; import {
StaticReflector,
StaticReflectorHost,
StaticSymbol,
ModuleContext
} from 'angular2/src/compiler/static_reflector';
export function main() { export function main() {
// Static reflector is not supported in Dart // Static reflector is not supported in Dart
// as we use reflection to create objects. // as we use reflection to create objects.
if (IS_DART) return; if (IS_DART) return;
let noContext = new ModuleContext('', '');
describe('StaticReflector', () => { describe('StaticReflector', () => {
let host: StaticReflectorHost; let host: StaticReflectorHost;
@ -18,17 +24,16 @@ export function main() {
reflector = new StaticReflector(host); reflector = new StaticReflector(host);
}); });
function singleModuleSimplify(moduleContext: string, value: any) { function singleModuleSimplify(moduleContext: ModuleContext, value: any) {
return reflector.simplify(moduleContext, value, false); return reflector.simplify(moduleContext, value, false);
} }
function crossModuleSimplify(moduleContext: string, value: any) { function crossModuleSimplify(moduleContext: ModuleContext, value: any) {
return reflector.simplify(moduleContext, value, true); return reflector.simplify(moduleContext, value, true);
} }
it('should get annotations for NgFor', () => { it('should get annotations for NgFor', () => {
let NgFor = reflector.getStaticType( let NgFor = host.findDeclaration('angular2/src/common/directives/ng_for', 'NgFor');
host.resolveModule('angular2/src/common/directives/ng_for'), 'NgFor');
let annotations = reflector.annotations(NgFor); let annotations = reflector.annotations(NgFor);
expect(annotations.length).toEqual(1); expect(annotations.length).toEqual(1);
let annotation = annotations[0]; let annotation = annotations[0];
@ -38,18 +43,15 @@ export function main() {
}); });
it('should get constructor for NgFor', () => { it('should get constructor for NgFor', () => {
let NgFor = reflector.getStaticType( let NgFor = host.findDeclaration('angular2/src/common/directives/ng_for', 'NgFor');
host.resolveModule('angular2/src/common/directives/ng_for'), 'NgFor'); let ViewContainerRef =
let ViewContainerRef = reflector.getStaticType( host.findDeclaration('angular2/src/core/linker/view_container_ref', 'ViewContainerRef');
host.resolveModule('angular2/src/core/linker/view_container_ref'), 'ViewContainerRef'); let TemplateRef =
let TemplateRef = reflector.getStaticType( host.findDeclaration('angular2/src/core/linker/template_ref', 'TemplateRef');
host.resolveModule('angular2/src/core/linker/template_ref'), 'TemplateRef'); let IterableDiffers = host.findDeclaration(
let IterableDiffers = reflector.getStaticType( 'angular2/src/core/change_detection/differs/iterable_differs', 'IterableDiffers');
host.resolveModule('angular2/src/core/change_detection/differs/iterable_differs'), let ChangeDetectorRef = host.findDeclaration(
'IterableDiffers'); 'angular2/src/core/change_detection/change_detector_ref', 'ChangeDetectorRef');
let ChangeDetectorRef = reflector.getStaticType(
host.resolveModule('angular2/src/core/change_detection/change_detector_ref'),
'ChangeDetectorRef');
let parameters = reflector.parameters(NgFor); let parameters = reflector.parameters(NgFor);
expect(parameters) expect(parameters)
@ -58,204 +60,208 @@ export function main() {
it('should get annotations for HeroDetailComponent', () => { it('should get annotations for HeroDetailComponent', () => {
let HeroDetailComponent = let HeroDetailComponent =
reflector.getStaticType('/src/app/hero-detail.component.ts', 'HeroDetailComponent'); host.findDeclaration('src/app/hero-detail.component', 'HeroDetailComponent');
let annotations = reflector.annotations(HeroDetailComponent); let annotations = reflector.annotations(HeroDetailComponent);
expect(annotations.length).toEqual(1); expect(annotations.length).toEqual(1);
let annotation = annotations[0]; let annotation = annotations[0];
expect(annotation.selector).toEqual('my-hero-detail'); expect(annotation.selector).toEqual('my-hero-detail');
expect(annotation.directives) expect(annotation.directives)
.toEqual([ .toEqual([[host.findDeclaration('angular2/src/common/directives/ng_for', 'NgFor')]]);
[
reflector.getStaticType(host.resolveModule('angular2/src/common/directives/ng_for'),
'NgFor')
]
]);
}); });
it('should get and empty annotation list for an unknown class', () => { it('should get and empty annotation list for an unknown class', () => {
let UnknownClass = reflector.getStaticType('/src/app/app.component.ts', 'UnknownClass'); let UnknownClass = host.findDeclaration('src/app/app.component', 'UnknownClass');
let annotations = reflector.annotations(UnknownClass); let annotations = reflector.annotations(UnknownClass);
expect(annotations).toEqual([]); expect(annotations).toEqual([]);
}); });
it('should get propMetadata for HeroDetailComponent', () => { it('should get propMetadata for HeroDetailComponent', () => {
let HeroDetailComponent = let HeroDetailComponent =
reflector.getStaticType('/src/app/hero-detail.component.ts', 'HeroDetailComponent'); host.findDeclaration('src/app/hero-detail.component', 'HeroDetailComponent');
let props = reflector.propMetadata(HeroDetailComponent); let props = reflector.propMetadata(HeroDetailComponent);
expect(props['hero']).toBeTruthy(); expect(props['hero']).toBeTruthy();
}); });
it('should get an empty object from propMetadata for an unknown class', () => { it('should get an empty object from propMetadata for an unknown class', () => {
let UnknownClass = reflector.getStaticType('/src/app/app.component.ts', 'UnknownClass'); let UnknownClass = host.findDeclaration('src/app/app.component', 'UnknownClass');
let properties = reflector.propMetadata(UnknownClass); let properties = reflector.propMetadata(UnknownClass);
expect(properties).toEqual({}); expect(properties).toEqual({});
}); });
it('should get empty parameters list for an unknown class ', () => { it('should get empty parameters list for an unknown class ', () => {
let UnknownClass = reflector.getStaticType('/src/app/app.component.ts', 'UnknownClass'); let UnknownClass = host.findDeclaration('src/app/app.component', 'UnknownClass');
let parameters = reflector.parameters(UnknownClass); let parameters = reflector.parameters(UnknownClass);
expect(parameters).toEqual([]); expect(parameters).toEqual([]);
}); });
it('should simplify primitive into itself', () => { it('should simplify primitive into itself', () => {
expect(singleModuleSimplify('', 1)).toBe(1); expect(singleModuleSimplify(noContext, 1)).toBe(1);
expect(singleModuleSimplify('', true)).toBe(true); expect(singleModuleSimplify(noContext, true)).toBe(true);
expect(singleModuleSimplify('', "some value")).toBe("some value"); expect(singleModuleSimplify(noContext, "some value")).toBe("some value");
}); });
it('should simplify an array into a copy of the array', it('should simplify an array into a copy of the array',
() => { expect(singleModuleSimplify('', [1, 2, 3])).toEqual([1, 2, 3]); }); () => { expect(singleModuleSimplify(noContext, [1, 2, 3])).toEqual([1, 2, 3]); });
it('should simplify an object to a copy of the object', () => { it('should simplify an object to a copy of the object', () => {
let expr = {a: 1, b: 2, c: 3}; let expr = {a: 1, b: 2, c: 3};
expect(singleModuleSimplify('', expr)).toEqual(expr); expect(singleModuleSimplify(noContext, expr)).toEqual(expr);
}); });
it('should simplify &&', () => { it('should simplify &&', () => {
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '&&', left: true, right: true}))).toBe(true); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '&&', left: true, right: true}))).toBe(true);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '&&', left: true, right: false}))).toBe(false); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '&&', left: true, right: false}))).toBe(false);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '&&', left: false, right: true}))).toBe(false); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '&&', left: false, right: true}))).toBe(false);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '&&', left: false, right: false}))).toBe(false); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '&&', left: false, right: false}))).toBe(false);
}); });
it('should simplify ||', () => { it('should simplify ||', () => {
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '||', left: true, right: true}))).toBe(true); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '||', left: true, right: true}))).toBe(true);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '||', left: true, right: false}))).toBe(true); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '||', left: true, right: false}))).toBe(true);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '||', left: false, right: true}))).toBe(true); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '||', left: false, right: true}))).toBe(true);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '||', left: false, right: false}))).toBe(false); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '||', left: false, right: false}))).toBe(false);
}); });
it('should simplify &', () => { it('should simplify &', () => {
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '&', left: 0x22, right: 0x0F}))).toBe(0x22 & 0x0F); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '&', left: 0x22, right: 0x0F}))).toBe(0x22 & 0x0F);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '&', left: 0x22, right: 0xF0}))).toBe(0x22 & 0xF0); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '&', left: 0x22, right: 0xF0}))).toBe(0x22 & 0xF0);
}); });
it('should simplify |', () => { it('should simplify |', () => {
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '|', left: 0x22, right: 0x0F}))).toBe(0x22 | 0x0F); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '|', left: 0x22, right: 0x0F}))).toBe(0x22 | 0x0F);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '|', left: 0x22, right: 0xF0}))).toBe(0x22 | 0xF0); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '|', left: 0x22, right: 0xF0}))).toBe(0x22 | 0xF0);
}); });
it('should simplify ^', () => { it('should simplify ^', () => {
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '|', left: 0x22, right: 0x0F}))).toBe(0x22 | 0x0F); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '|', left: 0x22, right: 0x0F}))).toBe(0x22 | 0x0F);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '|', left: 0x22, right: 0xF0}))).toBe(0x22 | 0xF0); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '|', left: 0x22, right: 0xF0}))).toBe(0x22 | 0xF0);
}); });
it('should simplify ==', () => { it('should simplify ==', () => {
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '==', left: 0x22, right: 0x22}))).toBe(0x22 == 0x22); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '==', left: 0x22, right: 0x22}))).toBe(0x22 == 0x22);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '==', left: 0x22, right: 0xF0}))).toBe(0x22 == 0xF0); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '==', left: 0x22, right: 0xF0}))).toBe(0x22 == 0xF0);
}); });
it('should simplify !=', () => { it('should simplify !=', () => {
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '!=', left: 0x22, right: 0x22}))).toBe(0x22 != 0x22); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '!=', left: 0x22, right: 0x22}))).toBe(0x22 != 0x22);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '!=', left: 0x22, right: 0xF0}))).toBe(0x22 != 0xF0); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '!=', left: 0x22, right: 0xF0}))).toBe(0x22 != 0xF0);
}); });
it('should simplify ===', () => { it('should simplify ===', () => {
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '===', left: 0x22, right: 0x22}))).toBe(0x22 === 0x22); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '===', left: 0x22, right: 0x22}))).toBe(0x22 === 0x22);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '===', left: 0x22, right: 0xF0}))).toBe(0x22 === 0xF0); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '===', left: 0x22, right: 0xF0}))).toBe(0x22 === 0xF0);
}); });
it('should simplify !==', () => { it('should simplify !==', () => {
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '!==', left: 0x22, right: 0x22}))).toBe(0x22 !== 0x22); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '!==', left: 0x22, right: 0x22}))).toBe(0x22 !== 0x22);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '!==', left: 0x22, right: 0xF0}))).toBe(0x22 !== 0xF0); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '!==', left: 0x22, right: 0xF0}))).toBe(0x22 !== 0xF0);
}); });
it('should simplify >', () => { it('should simplify >', () => {
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '>', left: 1, right: 1}))).toBe(1 > 1); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '>', left: 1, right: 1}))).toBe(1 > 1);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '>', left: 1, right: 0}))).toBe(1 > 0); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '>', left: 1, right: 0}))).toBe(1 > 0);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '>', left: 0, right: 1}))).toBe(0 > 1); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '>', left: 0, right: 1}))).toBe(0 > 1);
}); });
it('should simplify >=', () => { it('should simplify >=', () => {
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '>=', left: 1, right: 1}))).toBe(1 >= 1); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '>=', left: 1, right: 1}))).toBe(1 >= 1);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '>=', left: 1, right: 0}))).toBe(1 >= 0); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '>=', left: 1, right: 0}))).toBe(1 >= 0);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '>=', left: 0, right: 1}))).toBe(0 >= 1); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '>=', left: 0, right: 1}))).toBe(0 >= 1);
}); });
it('should simplify <=', () => { it('should simplify <=', () => {
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '<=', left: 1, right: 1}))).toBe(1 <= 1); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '<=', left: 1, right: 1}))).toBe(1 <= 1);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '<=', left: 1, right: 0}))).toBe(1 <= 0); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '<=', left: 1, right: 0}))).toBe(1 <= 0);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '<=', left: 0, right: 1}))).toBe(0 <= 1); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '<=', left: 0, right: 1}))).toBe(0 <= 1);
}); });
it('should simplify <', () => { it('should simplify <', () => {
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '<', left: 1, right: 1}))).toBe(1 < 1); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '<', left: 1, right: 1}))).toBe(1 < 1);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '<', left: 1, right: 0}))).toBe(1 < 0); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '<', left: 1, right: 0}))).toBe(1 < 0);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '<', left: 0, right: 1}))).toBe(0 < 1); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '<', left: 0, right: 1}))).toBe(0 < 1);
}); });
it('should simplify <<', () => { it('should simplify <<', () => {
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '<<', left: 0x55, right: 2}))).toBe(0x55 << 2); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '<<', left: 0x55, right: 2}))).toBe(0x55 << 2);
}); });
it('should simplify >>', () => { it('should simplify >>', () => {
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '>>', left: 0x55, right: 2}))).toBe(0x55 >> 2); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '>>', left: 0x55, right: 2}))).toBe(0x55 >> 2);
}); });
it('should simplify +', () => { it('should simplify +', () => {
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '+', left: 0x55, right: 2}))).toBe(0x55 + 2); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '+', left: 0x55, right: 2}))).toBe(0x55 + 2);
}); });
it('should simplify -', () => { it('should simplify -', () => {
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '-', left: 0x55, right: 2}))).toBe(0x55 - 2); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '-', left: 0x55, right: 2}))).toBe(0x55 - 2);
}); });
it('should simplify *', () => { it('should simplify *', () => {
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '*', left: 0x55, right: 2}))).toBe(0x55 * 2); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '*', left: 0x55, right: 2}))).toBe(0x55 * 2);
}); });
it('should simplify /', () => { it('should simplify /', () => {
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '/', left: 0x55, right: 2}))).toBe(0x55 / 2); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '/', left: 0x55, right: 2}))).toBe(0x55 / 2);
}); });
it('should simplify %', () => { it('should simplify %', () => {
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '%', left: 0x55, right: 2}))).toBe(0x55 % 2); expect(singleModuleSimplify(noContext, ({ __symbolic: 'binop', operator: '%', left: 0x55, right: 2}))).toBe(0x55 % 2);
}); });
it('should simplify prefix -', () => { it('should simplify prefix -', () => {
expect(singleModuleSimplify('', ({ __symbolic: 'pre', operator: '-', operand: 2}))).toBe(-2); expect(singleModuleSimplify(noContext, ({ __symbolic: 'pre', operator: '-', operand: 2}))).toBe(-2);
}); });
it('should simplify prefix ~', () => { it('should simplify prefix ~', () => {
expect(singleModuleSimplify('', ({ __symbolic: 'pre', operator: '~', operand: 2}))).toBe(~2); expect(singleModuleSimplify(noContext, ({ __symbolic: 'pre', operator: '~', operand: 2}))).toBe(~2);
}); });
it('should simplify prefix !', () => { it('should simplify prefix !', () => {
expect(singleModuleSimplify('', ({ __symbolic: 'pre', operator: '!', operand: true}))).toBe(!true); expect(singleModuleSimplify(noContext, ({ __symbolic: 'pre', operator: '!', operand: true}))).toBe(!true);
expect(singleModuleSimplify('', ({ __symbolic: 'pre', operator: '!', operand: false}))).toBe(!false); expect(singleModuleSimplify(noContext, ({ __symbolic: 'pre', operator: '!', operand: false}))).toBe(!false);
}); });
it('should simplify an array index', () => { it('should simplify an array index', () => {
expect(singleModuleSimplify('', ({__symbolic: "index", expression: [1, 2, 3], index: 2}))) expect(
singleModuleSimplify(noContext, ({__symbolic: "index", expression: [1, 2, 3], index: 2})))
.toBe(3); .toBe(3);
}); });
it('should simplify an object index', () => { it('should simplify an object index', () => {
let expr = {__symbolic: "select", expression: {a: 1, b: 2, c: 3}, member: "b"}; let expr = {__symbolic: "select", expression: {a: 1, b: 2, c: 3}, member: "b"};
expect(singleModuleSimplify('', expr)).toBe(2); expect(singleModuleSimplify(noContext, expr)).toBe(2);
}); });
it('should simplify a module reference across modules', () => { it('should simplify a module reference across modules', () => {
expect(crossModuleSimplify('/src/cases', expect(crossModuleSimplify({moduleId: '', filePath: '/src/cases'},
({__symbolic: "reference", module: "./extern", name: "s"}))) ({__symbolic: "reference", module: "./extern", name: "s"})))
.toEqual("s"); .toEqual("s");
}); });
it('should simplify a module reference without crossing modules', () => { it('should simplify a module reference without crossing modules', () => {
expect(singleModuleSimplify('/src/cases', expect(singleModuleSimplify({moduleId: '', filePath: '/src/cases'},
({__symbolic: "reference", module: "./extern", name: "s"}))) ({__symbolic: "reference", module: "./extern", name: "s"})))
.toEqual(reflector.getStaticType('/src/extern.d.ts', 's')); .toEqual(host.getStaticSymbol('', '/src/extern.d.ts', 's'));
}); });
}); });
} }
class MockReflectorHost implements StaticReflectorHost { class MockReflectorHost implements StaticReflectorHost {
// In tests, assume that symbols are not re-exported private staticTypeCache = new Map<string, StaticSymbol>();
findDeclaration(modulePath: string,
symbolName: string): {declarationPath: string, declaredName: string} { getStaticSymbol(moduleId: string, declarationFile: string, name: string): StaticSymbol {
return {declarationPath: modulePath, declaredName: symbolName}; var cacheKey = `${declarationFile}:${name}`;
var result = this.staticTypeCache.get(cacheKey);
if (isBlank(result)) {
result = new StaticSymbol(moduleId, declarationFile, name);
this.staticTypeCache.set(cacheKey, result);
} }
resolveModule(moduleName: string, containingFile?: string): string { return result;
}
// In tests, assume that symbols are not re-exported
findDeclaration(modulePath: string, symbolName: string, containingFile: string): StaticSymbol {
function splitPath(path: string): string[] { return path.split(/\/|\\/g); } function splitPath(path: string): string[] { return path.split(/\/|\\/g); }
function resolvePath(pathParts: string[]): string { function resolvePath(pathParts: string[]): string {
@ -286,10 +292,11 @@ class MockReflectorHost implements StaticReflectorHost {
return result; return result;
} }
if (moduleName.indexOf('.') === 0) { if (modulePath.indexOf('.') === 0) {
return pathTo(containingFile, moduleName) + '.d.ts'; return this.getStaticSymbol(`mod/${symbolName}`, pathTo(containingFile, modulePath) + '.d.ts',
symbolName);
} }
return '/tmp/' + moduleName + '.d.ts'; return this.getStaticSymbol(`mod/${symbolName}`, '/tmp/' + modulePath + '.d.ts', symbolName);
} }
getMetadataFor(moduleId: string): any { getMetadataFor(moduleId: string): any {
@ -376,7 +383,7 @@ class MockReflectorHost implements StaticReflectorHost {
{"metadata": {"IterableDiffers": {"__symbolic": "class"}}}, {"metadata": {"IterableDiffers": {"__symbolic": "class"}}},
'/tmp/angular2/src/core/change_detection/change_detector_ref.d.ts': '/tmp/angular2/src/core/change_detection/change_detector_ref.d.ts':
{"metadata": {"ChangeDetectorRef": {"__symbolic": "class"}}}, {"metadata": {"ChangeDetectorRef": {"__symbolic": "class"}}},
'/src/app/hero-detail.component.ts': '/tmp/src/app/hero-detail.component.d.ts':
{ {
"__symbolic": "module", "__symbolic": "module",
"metadata": "metadata":

View File

@ -398,7 +398,7 @@ class _DirectiveMetadataVisitor extends Object
_hasMetadata = true; _hasMetadata = true;
if (isComponent) { if (isComponent) {
_cmpTemplate = _cmpTemplate =
new _CompileTemplateMetadataVisitor().visitAnnotation(node); new _CompileTemplateMetadataVisitor(toAssetUri(_assetId)).visitAnnotation(node);
_validateTemplates(); _validateTemplates();
} }
super.visitAnnotation(node); super.visitAnnotation(node);
@ -411,7 +411,7 @@ class _DirectiveMetadataVisitor extends Object
'$node' /* source */); '$node' /* source */);
} }
_viewTemplate = _viewTemplate =
new _CompileTemplateMetadataVisitor().visitAnnotation(node); new _CompileTemplateMetadataVisitor(toAssetUri(_assetId)).visitAnnotation(node);
_validateTemplates(); _validateTemplates();
} }
@ -720,12 +720,15 @@ class _LifecycleHookVisitor extends SimpleAstVisitor<List<LifecycleHooks>> {
/// [CompileTemplateMetadata]. /// [CompileTemplateMetadata].
class _CompileTemplateMetadataVisitor class _CompileTemplateMetadataVisitor
extends RecursiveAstVisitor<CompileTemplateMetadata> { extends RecursiveAstVisitor<CompileTemplateMetadata> {
String _baseUrl;
ViewEncapsulation _encapsulation; ViewEncapsulation _encapsulation;
String _template; String _template;
String _templateUrl; String _templateUrl;
List<String> _styles; List<String> _styles;
List<String> _styleUrls; List<String> _styleUrls;
_CompileTemplateMetadataVisitor(this._baseUrl);
@override @override
CompileTemplateMetadata visitAnnotation(Annotation node) { CompileTemplateMetadata visitAnnotation(Annotation node) {
super.visitAnnotation(node); super.visitAnnotation(node);
@ -743,7 +746,8 @@ class _CompileTemplateMetadataVisitor
template: _template, template: _template,
templateUrl: _templateUrl, templateUrl: _templateUrl,
styles: _styles, styles: _styles,
styleUrls: _styleUrls); styleUrls: _styleUrls,
baseUrl: _baseUrl);
} }
@override @override