refactor(compiler): make static reflector work

Also adjust `RuntimeMetadataResolver` to
be able to use it. 

Also rename `RuntimeMetadataResolver` into `CompileMetadataResolver`.
Closes #8313
This commit is contained in:
Alex Eagle 2016-02-18 10:53:21 -08:00 committed by Tobias Bosch
parent 769835e53e
commit 70b23ae2ca
8 changed files with 447 additions and 512 deletions

View File

@ -17,7 +17,7 @@ import {provide, Provider} from 'angular2/src/core/di';
import {TemplateParser} from 'angular2/src/compiler/template_parser';
import {HtmlParser} from 'angular2/src/compiler/html_parser';
import {DirectiveNormalizer} from 'angular2/src/compiler/directive_normalizer';
import {RuntimeMetadataResolver} from 'angular2/src/compiler/runtime_metadata';
import {CompileMetadataResolver} from 'angular2/src/compiler/metadata_resolver';
import {StyleCompiler} from 'angular2/src/compiler/style_compiler';
import {ViewCompiler} from 'angular2/src/compiler/view_compiler/view_compiler';
import {CompilerConfig} from './config';
@ -46,7 +46,7 @@ export const COMPILER_PROVIDERS: Array<Type | Provider | any[]> = CONST_EXPR([
HtmlParser,
TemplateParser,
DirectiveNormalizer,
RuntimeMetadataResolver,
CompileMetadataResolver,
DEFAULT_PACKAGE_URL_PROVIDER,
StyleCompiler,
ViewCompiler,

View File

@ -6,12 +6,12 @@ import {
isArray,
stringify,
isString,
isStringMap,
RegExpWrapper,
StringWrapper
} from 'angular2/src/facade/lang';
import {StringMapWrapper} from 'angular2/src/facade/collection';
import {BaseException} from 'angular2/src/facade/exceptions';
import {NoAnnotationError} from 'angular2/src/core/di/reflective_exceptions';
import * as cpl from './compile_metadata';
import * as md from 'angular2/src/core/metadata/directives';
import * as dimd from 'angular2/src/core/metadata/di';
@ -28,20 +28,18 @@ import {MODULE_SUFFIX, sanitizeIdentifier} from './util';
import {assertArrayOfStrings} from './assertions';
import {getUrlScheme} from 'angular2/src/compiler/url_resolver';
import {Provider} from 'angular2/src/core/di/provider';
import {
constructDependencies,
ReflectiveDependency
} from 'angular2/src/core/di/reflective_provider';
import {
OptionalMetadata,
SelfMetadata,
HostMetadata,
SkipSelfMetadata
SkipSelfMetadata,
InjectMetadata
} from 'angular2/src/core/di/metadata';
import {AttributeMetadata, QueryMetadata} from 'angular2/src/core/metadata/di';
import {ReflectorReader} from 'angular2/src/core/reflection/reflector_reader';
@Injectable()
export class RuntimeMetadataResolver {
export class CompileMetadataResolver {
private _directiveCache = new Map<Type, cpl.CompileDirectiveMetadata>();
private _pipeCache = new Map<Type, cpl.CompilePipeMetadata>();
private _anonymousTypes = new Map<Object, number>();
@ -78,7 +76,7 @@ export class RuntimeMetadataResolver {
var meta = this._directiveCache.get(directiveType);
if (isBlank(meta)) {
var dirMeta = this._directiveResolver.resolve(directiveType);
var moduleUrl = null;
var moduleUrl = staticTypeModuleUrl(directiveType);
var templateMeta = null;
var changeDetectionStrategy = null;
var viewProviders = [];
@ -134,6 +132,21 @@ export class RuntimeMetadataResolver {
return meta;
}
/**
* @param someType a symbol which may or may not be a directive type
* @returns {cpl.CompileDirectiveMetadata} if possible, otherwise null.
*/
maybeGetDirectiveMetadata(someType: Type): cpl.CompileDirectiveMetadata {
try {
return this.getDirectiveMetadata(someType);
} catch (e) {
if (e.message.indexOf('No Directive annotation') !== -1) {
return null;
}
throw e;
}
}
getTypeMetadata(type: Type, moduleUrl: string): cpl.CompileTypeMetadata {
return new cpl.CompileTypeMetadata({
name: this.sanitizeTokenName(type),
@ -156,9 +169,8 @@ export class RuntimeMetadataResolver {
var meta = this._pipeCache.get(pipeType);
if (isBlank(meta)) {
var pipeMeta = this._pipeResolver.resolve(pipeType);
var moduleUrl = this._reflector.importUri(pipeType);
meta = new cpl.CompilePipeMetadata({
type: this.getTypeMetadata(pipeType, moduleUrl),
type: this.getTypeMetadata(pipeType, staticTypeModuleUrl(pipeType)),
name: pipeMeta.name,
pure: pipeMeta.pure,
lifecycleHooks: LIFECYCLE_HOOKS_VALUES.filter(hook => hasLifecycleHook(hook, pipeType)),
@ -177,7 +189,6 @@ export class RuntimeMetadataResolver {
`Unexpected directive value '${stringify(directives[i])}' on the View of component '${stringify(component)}'`);
}
}
return directives.map(type => this.getDirectiveMetadata(type));
}
@ -195,41 +206,65 @@ export class RuntimeMetadataResolver {
getDependenciesMetadata(typeOrFunc: Type | Function,
dependencies: any[]): cpl.CompileDiDependencyMetadata[] {
var deps: ReflectiveDependency[];
try {
deps = constructDependencies(typeOrFunc, dependencies);
} catch (e) {
if (e instanceof NoAnnotationError) {
deps = [];
} else {
throw e;
}
let params = isPresent(dependencies) ? dependencies : this._reflector.parameters(typeOrFunc);
if (isBlank(params)) {
params = [];
}
return deps.map((dep) => {
var compileToken;
var p = <dimd.AttributeMetadata>dep.properties.find(p => p instanceof dimd.AttributeMetadata);
var isAttribute = false;
if (isPresent(p)) {
compileToken = this.getTokenMetadata(p.attributeName);
isAttribute = true;
} else {
compileToken = this.getTokenMetadata(dep.key.token);
return params.map((param) => {
if (isBlank(param)) {
return null;
}
var compileQuery = null;
var q = <dimd.QueryMetadata>dep.properties.find(p => p instanceof dimd.QueryMetadata);
if (isPresent(q)) {
compileQuery = this.getQueryMetadata(q, null);
let isAttribute = false;
let isHost = false;
let isSelf = false;
let isSkipSelf = false;
let isOptional = false;
let query: dimd.QueryMetadata = null;
let viewQuery: dimd.ViewQueryMetadata = null;
var token = null;
if (isArray(param)) {
(<any[]>param)
.forEach((paramEntry) => {
if (paramEntry instanceof HostMetadata) {
isHost = true;
} else if (paramEntry instanceof SelfMetadata) {
isSelf = true;
} else if (paramEntry instanceof SkipSelfMetadata) {
isSkipSelf = true;
} else if (paramEntry instanceof OptionalMetadata) {
isOptional = true;
} else if (paramEntry instanceof AttributeMetadata) {
isAttribute = true;
token = paramEntry.attributeName;
} else if (paramEntry instanceof QueryMetadata) {
if (paramEntry.isViewQuery) {
viewQuery = paramEntry;
} else {
query = paramEntry;
}
} else if (paramEntry instanceof InjectMetadata) {
token = paramEntry.token;
} else if (isValidType(paramEntry) && isBlank(token)) {
token = paramEntry;
}
});
} else {
token = param;
}
if (isBlank(token)) {
return null;
}
return new cpl.CompileDiDependencyMetadata({
isAttribute: isAttribute,
isHost: dep.upperBoundVisibility instanceof HostMetadata,
isSelf: dep.upperBoundVisibility instanceof SelfMetadata,
isSkipSelf: dep.lowerBoundVisibility instanceof SkipSelfMetadata,
isOptional: dep.optional,
query: isPresent(q) && !q.isViewQuery ? compileQuery : null,
viewQuery: isPresent(q) && q.isViewQuery ? compileQuery : null,
token: compileToken
isHost: isHost,
isSelf: isSelf,
isSkipSelf: isSkipSelf,
isOptional: isOptional,
query: isPresent(query) ? this.getQueryMetadata(query, null) : null,
viewQuery: isPresent(viewQuery) ? this.getQueryMetadata(viewQuery, null) : null,
token: this.getTokenMetadata(token)
});
});
}
@ -240,8 +275,11 @@ export class RuntimeMetadataResolver {
compileToken = new cpl.CompileTokenMetadata({value: token});
} else {
compileToken = new cpl.CompileTokenMetadata({
identifier: new cpl.CompileIdentifierMetadata(
{runtime: token, name: this.sanitizeTokenName(token)})
identifier: new cpl.CompileIdentifierMetadata({
runtime: token,
name: this.sanitizeTokenName(token),
moduleUrl: staticTypeModuleUrl(token)
})
});
}
return compileToken;
@ -256,7 +294,7 @@ export class RuntimeMetadataResolver {
} else if (provider instanceof Provider) {
return this.getProviderMetadata(provider);
} else {
return this.getTypeMetadata(provider, null);
return this.getTypeMetadata(provider, staticTypeModuleUrl(provider));
}
});
}
@ -270,12 +308,16 @@ export class RuntimeMetadataResolver {
}
return new cpl.CompileProviderMetadata({
token: this.getTokenMetadata(provider.token),
useClass: isPresent(provider.useClass) ? this.getTypeMetadata(provider.useClass, null) : null,
useClass:
isPresent(provider.useClass) ?
this.getTypeMetadata(provider.useClass, staticTypeModuleUrl(provider.useClass)) :
null,
useValue: isPresent(provider.useValue) ?
new cpl.CompileIdentifierMetadata({runtime: provider.useValue}) :
null,
useFactory: isPresent(provider.useFactory) ?
this.getFactoryMetadata(provider.useFactory, null) :
this.getFactoryMetadata(provider.useFactory,
staticTypeModuleUrl(provider.useFactory)) :
null,
useExisting: isPresent(provider.useExisting) ? this.getTokenMetadata(provider.useExisting) :
null,
@ -345,8 +387,16 @@ function flattenArray(tree: any[], out: Array<Type | any[]>): void {
}
}
function isValidType(value: Type): boolean {
return isPresent(value) && (value instanceof Type);
function isStaticType(value: any): boolean {
return isStringMap(value) && isPresent(value['name']) && isPresent(value['moduleId']);
}
function isValidType(value: any): boolean {
return isStaticType(value) || (value instanceof Type);
}
function staticTypeModuleUrl(value: any): string {
return isStaticType(value) ? value['moduleId'] : null;
}
function calcModuleUrl(reflector: ReflectorReader, type: Type,

View File

@ -44,7 +44,7 @@ import {StyleCompiler, StylesCompileDependency, StylesCompileResult} from './sty
import {ViewCompiler} from './view_compiler/view_compiler';
import {TemplateParser} from './template_parser';
import {DirectiveNormalizer} from './directive_normalizer';
import {RuntimeMetadataResolver} from './runtime_metadata';
import {CompileMetadataResolver} from './metadata_resolver';
import {ComponentFactory} from 'angular2/src/core/linker/component_factory';
import {
ComponentResolver,
@ -71,7 +71,7 @@ export class RuntimeCompiler implements ComponentResolver {
private _compiledTemplateCache = new Map<any, CompiledTemplate>();
private _compiledTemplateDone = new Map<any, Promise<CompiledTemplate>>();
constructor(private _runtimeMetadataResolver: RuntimeMetadataResolver,
constructor(private _metadataResolver: CompileMetadataResolver,
private _templateNormalizer: DirectiveNormalizer,
private _templateParser: TemplateParser, private _styleCompiler: StyleCompiler,
private _viewCompiler: ViewCompiler, private _xhr: XHR,
@ -79,7 +79,7 @@ export class RuntimeCompiler implements ComponentResolver {
resolveComponent(componentType: Type): Promise<ComponentFactory> {
var compMeta: CompileDirectiveMetadata =
this._runtimeMetadataResolver.getDirectiveMetadata(componentType);
this._metadataResolver.getDirectiveMetadata(componentType);
var hostCacheKey = this._hostCacheKeys.get(componentType);
if (isBlank(hostCacheKey)) {
hostCacheKey = new Object();
@ -146,9 +146,9 @@ export class RuntimeCompiler implements ComponentResolver {
var childCacheKey = dep.comp.type.runtime;
var childViewDirectives: CompileDirectiveMetadata[] =
this._runtimeMetadataResolver.getViewDirectivesMetadata(dep.comp.type.runtime);
this._metadataResolver.getViewDirectivesMetadata(dep.comp.type.runtime);
var childViewPipes: CompilePipeMetadata[] =
this._runtimeMetadataResolver.getViewPipesMetadata(dep.comp.type.runtime);
this._metadataResolver.getViewPipesMetadata(dep.comp.type.runtime);
var childIsRecursive = ListWrapper.contains(childCompilingComponentsPath, childCacheKey);
childCompilingComponentsPath.push(childCacheKey);

View File

@ -1,8 +1,12 @@
import {StringMapWrapper} from 'angular2/src/facade/collection';
import {StringMapWrapper, ListWrapper} from 'angular2/src/facade/collection';
import {
isArray,
isPresent,
isBlank,
isPrimitive,
isStringMap,
CONST_EXPR,
FunctionWrapper
} from 'angular2/src/facade/lang';
import {
AttributeMetadata,
@ -22,6 +26,16 @@ import {
QueryMetadata,
} from 'angular2/src/core/metadata';
import {ReflectorReader} from 'angular2/src/core/reflection/reflector_reader';
import {reflector} from 'angular2/src/core/reflection/reflection';
import {Provider} from 'angular2/src/core/di/provider';
import {
HostMetadata,
OptionalMetadata,
InjectableMetadata,
SelfMetadata,
SkipSelfMetadata,
InjectMetadata
} from "angular2/src/core/di/metadata";
/**
* The host of the static resolver is expected to be able to provide module metadata in the form of
@ -36,7 +50,7 @@ export interface StaticReflectorHost {
* @param moduleId is a string identifier for a module as an absolute path.
* @returns the metadata for the given module.
*/
getMetadataFor(moduleId: string): {[key: string]: any};
getMetadataFor(modulePath: string): {[key: string]: any};
/**
* Resolve a module from an import statement form to an absolute path.
@ -44,6 +58,9 @@ export interface StaticReflectorHost {
* @param containingFile for relative imports, the path of the file containing the import
*/
resolveModule(moduleName: string, containingFile?: string): string;
findDeclaration(modulePath: string,
symbolName: string): {declarationPath: string, declaredName: string};
}
/**
@ -65,6 +82,8 @@ export class StaticReflector implements ReflectorReader {
private propertyCache = new Map<StaticType, {[key: string]: any}>();
private parameterCache = new Map<StaticType, any[]>();
private metadataCache = new Map<string, {[key: string]: any}>();
private conversionMap = new Map<StaticType, (moduleContext: string, args: any[]) => any>();
constructor(private host: StaticReflectorHost) { this.initializeConversionMap(); }
importUri(typeOrFunc: any): string { return (<StaticType>typeOrFunc).moduleId; }
@ -91,13 +110,11 @@ export class StaticReflector implements ReflectorReader {
if (!isPresent(annotations)) {
let classMetadata = this.getTypeMetadata(type);
if (isPresent(classMetadata['decorators'])) {
annotations = (<any[]>classMetadata['decorators'])
.map(decorator => this.convertKnownDecorator(type.moduleId, decorator))
.filter(decorator => isPresent(decorator));
annotations = this.simplify(type.moduleId, classMetadata['decorators'], false);
} else {
annotations = [];
}
this.annotationCache.set(type, annotations);
this.annotationCache.set(type, annotations.filter(ann => isPresent(ann)));
}
return annotations;
}
@ -106,10 +123,15 @@ export class StaticReflector implements ReflectorReader {
let propMetadata = this.propertyCache.get(type);
if (!isPresent(propMetadata)) {
let classMetadata = this.getTypeMetadata(type);
propMetadata = this.getPropertyMetadata(type.moduleId, classMetadata['members']);
if (!isPresent(propMetadata)) {
propMetadata = {};
}
let members = isPresent(classMetadata) ? classMetadata['members'] : {};
propMetadata = mapStringMap(members, (propData, propName) => {
let prop = (<any[]>propData).find(a => a['__symbolic'] == 'property');
if (isPresent(prop) && isPresent(prop['decorators'])) {
return this.simplify(type.moduleId, prop['decorators'], false);
} else {
return [];
}
});
this.propertyCache.set(type, propMetadata);
}
return propMetadata;
@ -119,15 +141,26 @@ export class StaticReflector implements ReflectorReader {
let parameters = this.parameterCache.get(type);
if (!isPresent(parameters)) {
let classMetadata = this.getTypeMetadata(type);
if (isPresent(classMetadata)) {
let members = classMetadata['members'];
if (isPresent(members)) {
let ctorData = members['__ctor__'];
if (isPresent(ctorData)) {
let ctor = (<any[]>ctorData).find(a => a['__symbolic'] === 'constructor');
parameters = this.simplify(type.moduleId, ctor['parameters']);
let members = isPresent(classMetadata) ? classMetadata['members'] : null;
let ctorData = isPresent(members) ? members['__ctor__'] : null;
if (isPresent(ctorData)) {
let ctor = (<any[]>ctorData).find(a => a['__symbolic'] == 'constructor');
let parameterTypes = <any[]>this.simplify(type.moduleId, ctor['parameters'], false);
let parameterDecorators =
<any[]>this.simplify(type.moduleId, ctor['parameterDecorators'], false);
parameters = [];
ListWrapper.forEachWithIndex(parameterTypes, (paramType, index) => {
let nestedResult = [];
if (isPresent(paramType)) {
nestedResult.push(paramType);
}
}
let decorators = isPresent(parameterDecorators) ? parameterDecorators[index] : null;
if (isPresent(decorators)) {
ListWrapper.addAll(nestedResult, decorators);
}
parameters.push(nestedResult);
});
}
if (!isPresent(parameters)) {
parameters = [];
@ -137,201 +170,82 @@ export class StaticReflector implements ReflectorReader {
return parameters;
}
private conversionMap = new Map<StaticType, (moduleContext: string, expression: any) => any>();
private initializeConversionMap(): any {
let core_metadata = this.host.resolveModule('angular2/src/core/metadata');
let conversionMap = this.conversionMap;
conversionMap.set(this.getStaticType(core_metadata, 'Directive'),
(moduleContext, expression) => {
let p0 = this.getDecoratorParameter(moduleContext, expression, 0);
if (!isPresent(p0)) {
p0 = {};
}
return new DirectiveMetadata({
selector: p0['selector'],
inputs: p0['inputs'],
outputs: p0['outputs'],
events: p0['events'],
host: p0['host'],
bindings: p0['bindings'],
providers: p0['providers'],
exportAs: p0['exportAs'],
queries: p0['queries'],
});
});
conversionMap.set(this.getStaticType(core_metadata, 'Component'),
(moduleContext, expression) => {
let p0 = this.getDecoratorParameter(moduleContext, expression, 0);
if (!isPresent(p0)) {
p0 = {};
}
return new ComponentMetadata({
selector: p0['selector'],
inputs: p0['inputs'],
outputs: p0['outputs'],
properties: p0['properties'],
events: p0['events'],
host: p0['host'],
exportAs: p0['exportAs'],
moduleId: p0['moduleId'],
bindings: p0['bindings'],
providers: p0['providers'],
viewBindings: p0['viewBindings'],
viewProviders: p0['viewProviders'],
changeDetection: p0['changeDetection'],
queries: p0['queries'],
templateUrl: p0['templateUrl'],
template: p0['template'],
styleUrls: p0['styleUrls'],
styles: p0['styles'],
directives: p0['directives'],
pipes: p0['pipes'],
encapsulation: p0['encapsulation']
});
});
conversionMap.set(this.getStaticType(core_metadata, 'Input'),
(moduleContext, expression) => new InputMetadata(
this.getDecoratorParameter(moduleContext, expression, 0)));
conversionMap.set(this.getStaticType(core_metadata, 'Output'),
(moduleContext, expression) => new OutputMetadata(
this.getDecoratorParameter(moduleContext, expression, 0)));
conversionMap.set(this.getStaticType(core_metadata, 'View'), (moduleContext, expression) => {
let p0 = this.getDecoratorParameter(moduleContext, expression, 0);
if (!isPresent(p0)) {
p0 = {};
}
return new ViewMetadata({
templateUrl: p0['templateUrl'],
template: p0['template'],
directives: p0['directives'],
pipes: p0['pipes'],
encapsulation: p0['encapsulation'],
styles: p0['styles'],
});
});
conversionMap.set(this.getStaticType(core_metadata, 'Attribute'),
(moduleContext, expression) => new AttributeMetadata(
this.getDecoratorParameter(moduleContext, expression, 0)));
conversionMap.set(this.getStaticType(core_metadata, 'Query'), (moduleContext, expression) => {
let p0 = this.getDecoratorParameter(moduleContext, expression, 0);
let p1 = this.getDecoratorParameter(moduleContext, expression, 1);
if (!isPresent(p1)) {
p1 = {};
}
return new QueryMetadata(p0, {descendants: p1.descendants, first: p1.first});
});
conversionMap.set(this.getStaticType(core_metadata, 'ContentChildren'),
(moduleContext, expression) => new ContentChildrenMetadata(
this.getDecoratorParameter(moduleContext, expression, 0)));
conversionMap.set(this.getStaticType(core_metadata, 'ContentChild'),
(moduleContext, expression) => new ContentChildMetadata(
this.getDecoratorParameter(moduleContext, expression, 0)));
conversionMap.set(this.getStaticType(core_metadata, 'ViewChildren'),
(moduleContext, expression) => new ViewChildrenMetadata(
this.getDecoratorParameter(moduleContext, expression, 0)));
conversionMap.set(this.getStaticType(core_metadata, 'ViewChild'),
(moduleContext, expression) => new ViewChildMetadata(
this.getDecoratorParameter(moduleContext, expression, 0)));
conversionMap.set(this.getStaticType(core_metadata, 'ViewQuery'),
(moduleContext, expression) => {
let p0 = this.getDecoratorParameter(moduleContext, expression, 0);
let p1 = this.getDecoratorParameter(moduleContext, expression, 1);
if (!isPresent(p1)) {
p1 = {};
}
return new ViewQueryMetadata(p0, {
descendants: p1['descendants'],
first: p1['first'],
});
});
conversionMap.set(this.getStaticType(core_metadata, 'Pipe'), (moduleContext, expression) => {
let p0 = this.getDecoratorParameter(moduleContext, expression, 0);
if (!isPresent(p0)) {
p0 = {};
}
return new PipeMetadata({
name: p0['name'],
pure: p0['pure'],
});
});
conversionMap.set(this.getStaticType(core_metadata, 'HostBinding'),
(moduleContext, expression) => new HostBindingMetadata(
this.getDecoratorParameter(moduleContext, expression, 0)));
conversionMap.set(this.getStaticType(core_metadata, 'HostListener'),
(moduleContext, expression) => new HostListenerMetadata(
this.getDecoratorParameter(moduleContext, expression, 0),
this.getDecoratorParameter(moduleContext, expression, 1)));
return null;
}
private convertKnownDecorator(moduleContext: string, expression: {[key: string]: any}): any {
let converter = this.conversionMap.get(this.getDecoratorType(moduleContext, expression));
if (isPresent(converter)) return converter(moduleContext, expression);
return null;
}
private getDecoratorType(moduleContext: string, expression: {[key: string]: any}): StaticType {
if (isMetadataSymbolicCallExpression(expression)) {
let target = expression['expression'];
if (isMetadataSymbolicReferenceExpression(target)) {
let moduleId = this.host.resolveModule(target['module'], moduleContext);
return this.getStaticType(moduleId, target['name']);
}
}
return null;
}
private getDecoratorParameter(moduleContext: string, expression: {[key: string]: any},
index: number): any {
if (isMetadataSymbolicCallExpression(expression) && isPresent(expression['arguments']) &&
(<any[]>expression['arguments']).length <= index + 1) {
return this.simplify(moduleContext, (<any[]>expression['arguments'])[index]);
}
return null;
}
private getPropertyMetadata(moduleContext: string,
value: {[key: string]: any}): {[key: string]: any} {
if (isPresent(value)) {
let result = {};
StringMapWrapper.forEach(value, (value, name) => {
let data = this.getMemberData(moduleContext, value);
if (isPresent(data)) {
let propertyData = data.filter(d => d['kind'] == "property")
.map(d => d['directives'])
.reduce((p, c) => (<any[]>p).concat(<any[]>c), []);
if (propertyData.length != 0) {
StringMapWrapper.set(result, name, propertyData);
}
private registerDecoratorOrConstructor(type: StaticType, ctor: any,
crossModuleProps: any[] = CONST_EXPR([])): void {
this.conversionMap.set(type, (moduleContext: string, args: any[]) => {
let argValues = [];
ListWrapper.forEachWithIndex(args, (arg, index) => {
let argValue;
if (isStringMap(arg) && isBlank(arg['__symbolic'])) {
argValue =
mapStringMap(arg, (value, key) => this.simplify(
moduleContext, value, crossModuleProps.indexOf(key) !== -1));
} else {
argValue = this.simplify(moduleContext, arg, crossModuleProps.indexOf(index) !== -1);
}
argValues.push(argValue);
});
return result;
}
return {};
return FunctionWrapper.apply(reflector.factory(ctor), argValues);
});
}
// clang-format off
private getMemberData(moduleContext: string, member: { [key: string]: any }[]): { [key: string]: any }[] {
// clang-format on
let result = [];
if (isPresent(member)) {
for (let item of member) {
result.push({
kind: item['__symbolic'],
directives:
isPresent(item['decorators']) ?
(<any[]>item['decorators'])
.map(decorator => this.convertKnownDecorator(moduleContext, decorator))
.filter(d => isPresent(d)) :
null
});
}
}
return result;
private initializeConversionMap(): void {
let coreDecorators = this.host.resolveModule('angular2/src/core/metadata');
let diDecorators = this.host.resolveModule('angular2/src/core/di/decorators');
let diMetadata = this.host.resolveModule('angular2/src/core/di/metadata');
let provider = this.host.resolveModule('angular2/src/core/di/provider');
this.registerDecoratorOrConstructor(this.getStaticType(provider, 'Provider'), Provider);
this.registerDecoratorOrConstructor(this.getStaticType(diDecorators, 'Host'), HostMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(diDecorators, 'Injectable'),
InjectableMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(diDecorators, 'Self'), SelfMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(diDecorators, 'SkipSelf'),
SkipSelfMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(diDecorators, 'Inject'), InjectMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(diDecorators, 'Optional'),
OptionalMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'Attribute'),
AttributeMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'Query'), QueryMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'ViewQuery'),
ViewQueryMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'ContentChild'),
ContentChildMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'ContentChildren'),
ContentChildrenMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'ViewChild'),
ViewChildMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'ViewChildren'),
ViewChildrenMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'Input'), InputMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'Output'),
OutputMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'Pipe'), PipeMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'HostBinding'),
HostBindingMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'HostListener'),
HostListenerMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'Directive'),
DirectiveMetadata, ['bindings', 'providers']);
this.registerDecoratorOrConstructor(this.getStaticType(coreDecorators, 'Component'),
ComponentMetadata,
['bindings', 'providers', 'directives', 'pipes']);
// Note: Some metadata classes can be used directly with Provider.deps.
this.registerDecoratorOrConstructor(this.getStaticType(diMetadata, 'HostMetadata'),
HostMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(diMetadata, 'SelfMetadata'),
SelfMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(diMetadata, 'SkipSelfMetadata'),
SkipSelfMetadata);
this.registerDecoratorOrConstructor(this.getStaticType(diMetadata, 'OptionalMetadata'),
OptionalMetadata);
}
/** @internal */
public simplify(moduleContext: string, value: any): any {
public simplify(moduleContext: string, value: any, crossModules: boolean): any {
let _this = this;
function simplify(expression: any): any {
@ -418,23 +332,44 @@ export class StaticReflector implements ReflectorReader {
if (isPresent(selectTarget) && isPrimitive(member)) return selectTarget[member];
return null;
case "reference":
let referenceModuleName =
_this.host.resolveModule(expression['module'], moduleContext);
let referenceModule = _this.getModuleMetadata(referenceModuleName);
let referenceValue = referenceModule['metadata'][expression['name']];
if (isClassMetadata(referenceValue)) {
// Convert to a pseudo type
return _this.getStaticType(referenceModuleName, expression['name']);
let referenceModuleName;
let declarationPath = moduleContext;
let declaredName = expression['name'];
if (isPresent(expression['module'])) {
referenceModuleName = _this.host.resolveModule(expression['module'], moduleContext);
let decl = _this.host.findDeclaration(referenceModuleName, expression['name']);
declarationPath = decl['declarationPath'];
declaredName = decl['declaredName'];
}
return _this.simplify(referenceModuleName, referenceValue);
let result;
if (crossModules || isBlank(expression['module'])) {
let moduleMetadata = _this.getModuleMetadata(declarationPath);
let declarationValue = moduleMetadata['metadata'][declaredName];
if (isClassMetadata(declarationValue)) {
result = _this.getStaticType(declarationPath, declaredName);
} else {
result = _this.simplify(declarationPath, declarationValue, crossModules);
}
} else {
result = _this.getStaticType(declarationPath, declaredName);
}
return result;
case "new":
case "call":
return null;
let target = expression['expression'];
let moduleId = _this.host.resolveModule(target['module'], moduleContext);
let decl = _this.host.findDeclaration(moduleId, target['name']);
let staticType = _this.getStaticType(decl['declarationPath'], decl['declaredName']);
let converter = _this.conversionMap.get(staticType);
let args = expression['arguments'];
if (isBlank(args)) {
args = [];
}
return isPresent(converter) ? converter(moduleContext, args) : null;
}
return null;
}
let result = {};
StringMapWrapper.forEach(expression, (value, name) => { result[name] = simplify(value); });
return result;
return mapStringMap(expression, (value, name) => simplify(value));
}
return null;
}
@ -467,15 +402,14 @@ export class StaticReflector implements ReflectorReader {
}
}
function isMetadataSymbolicCallExpression(expression: any): boolean {
return !isPrimitive(expression) && !isArray(expression) && expression['__symbolic'] == 'call';
}
function isMetadataSymbolicReferenceExpression(expression: any): boolean {
return !isPrimitive(expression) && !isArray(expression) &&
expression['__symbolic'] == 'reference';
}
function isClassMetadata(expression: any): boolean {
return !isPrimitive(expression) && !isArray(expression) && expression['__symbolic'] == 'class';
}
function mapStringMap(input: {[key: string]: any},
transform: (value: any, key: string) => any): {[key: string]: any} {
if (isBlank(input)) return {};
var result = {};
StringMapWrapper.keys(input).forEach((key) => { result[key] = transform(input[key], key); });
return result;
}

View File

@ -1,4 +1,4 @@
library angular2.test.compiler.runtime_metadata_fixture;
library angular2.test.compiler.metadata_resolver_fixture;
import "package:angular2/core.dart" show Component;

View File

@ -14,7 +14,7 @@ import {
} from 'angular2/testing_internal';
import {IS_DART, stringify} from 'angular2/src/facade/lang';
import {RuntimeMetadataResolver} from 'angular2/src/compiler/runtime_metadata';
import {CompileMetadataResolver} from 'angular2/src/compiler/metadata_resolver';
import {LifecycleHooks, LIFECYCLE_HOOKS_VALUES} from 'angular2/src/core/metadata/lifecycle_hooks';
import {
Component,
@ -36,15 +36,15 @@ import {
import {TEST_PROVIDERS} from './test_bindings';
import {MODULE_SUFFIX} from 'angular2/src/compiler/util';
import {PLATFORM_DIRECTIVES} from 'angular2/src/core/platform_directives_and_pipes';
import {MalformedStylesComponent} from './runtime_metadata_fixture';
import {MalformedStylesComponent} from './metadata_resolver_fixture';
export function main() {
describe('RuntimeMetadataResolver', () => {
describe('CompileMetadataResolver', () => {
beforeEachProviders(() => TEST_PROVIDERS);
describe('getMetadata', () => {
it('should read metadata',
inject([RuntimeMetadataResolver], (resolver: RuntimeMetadataResolver) => {
inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
var meta = resolver.getDirectiveMetadata(ComponentWithEverything);
expect(meta.selector).toEqual('someSelector');
expect(meta.exportAs).toEqual('someExportAs');
@ -67,16 +67,16 @@ export function main() {
}));
it('should use the moduleUrl from the reflector if none is given',
inject([RuntimeMetadataResolver], (resolver: RuntimeMetadataResolver) => {
inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
var value: string =
resolver.getDirectiveMetadata(ComponentWithoutModuleId).type.moduleUrl;
var expectedEndValue =
IS_DART ? 'test/compiler/runtime_metadata_spec.dart' : './ComponentWithoutModuleId';
IS_DART ? 'test/compiler/metadata_resolver_spec.dart' : './ComponentWithoutModuleId';
expect(value.endsWith(expectedEndValue)).toBe(true);
}));
it('should throw when metadata is incorrectly typed',
inject([RuntimeMetadataResolver], (resolver: RuntimeMetadataResolver) => {
inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
if (!IS_DART) {
expect(() => resolver.getDirectiveMetadata(MalformedStylesComponent))
.toThrowError(`Expected 'styles' to be an array of strings.`);
@ -87,7 +87,7 @@ export function main() {
describe('getViewDirectivesMetadata', () => {
it('should return the directive metadatas',
inject([RuntimeMetadataResolver], (resolver: RuntimeMetadataResolver) => {
inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
expect(resolver.getViewDirectivesMetadata(ComponentWithEverything))
.toContain(resolver.getDirectiveMetadata(SomeDirective));
}));
@ -97,7 +97,7 @@ export function main() {
() => [provide(PLATFORM_DIRECTIVES, {useValue: [ADirective], multi: true})]);
it('should include platform directives when available',
inject([RuntimeMetadataResolver], (resolver: RuntimeMetadataResolver) => {
inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
expect(resolver.getViewDirectivesMetadata(ComponentWithEverything))
.toContain(resolver.getDirectiveMetadata(ADirective));
expect(resolver.getViewDirectivesMetadata(ComponentWithEverything))

View File

@ -1,18 +1,32 @@
import {
describe,
it,
expect,
} from 'angular2/testing_internal';
import {describe, it, iit, expect, ddescribe, beforeEach} from 'angular2/testing_internal';
import {IS_DART} from 'angular2/src/facade/lang';
import {ListWrapper} from 'angular2/src/facade/collection';
import {StaticReflector, StaticReflectorHost} from 'angular2/src/compiler/static_reflector';
export function main() {
describe('StaticReflector', () => {
it('should get annotations for NgFor', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
// Static reflector is not supported in Dart
// as we use reflection to create objects.
if (IS_DART) return;
describe('StaticReflector', () => {
let host: StaticReflectorHost;
let reflector: StaticReflector;
beforeEach(() => {
host = new MockReflectorHost();
reflector = new StaticReflector(host);
});
function singleModuleSimplify(moduleContext: string, value: any) {
return reflector.simplify(moduleContext, value, false);
}
function crossModuleSimplify(moduleContext: string, value: any) {
return reflector.simplify(moduleContext, value, true);
}
it('should get annotations for NgFor', () => {
let NgFor = reflector.getStaticType(
host.resolveModule('angular2/src/common/directives/ng_for'), 'NgFor');
let annotations = reflector.annotations(NgFor);
@ -20,12 +34,10 @@ export function main() {
let annotation = annotations[0];
expect(annotation.selector).toEqual('[ngFor][ngForOf]');
expect(annotation.inputs).toEqual(['ngForTrackBy', 'ngForOf', 'ngForTemplate']);
});
it('should get constructor for NgFor', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
let NgFor = reflector.getStaticType(
host.resolveModule('angular2/src/common/directives/ng_for'), 'NgFor');
let ViewContainerRef = reflector.getStaticType(
@ -41,34 +53,32 @@ export function main() {
let parameters = reflector.parameters(NgFor);
expect(parameters)
.toEqual([ViewContainerRef, TemplateRef, IterableDiffers, ChangeDetectorRef]);
.toEqual([[ViewContainerRef], [TemplateRef], [IterableDiffers], [ChangeDetectorRef]]);
});
it('should get annotations for HeroDetailComponent', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
let HeroDetailComponent =
reflector.getStaticType('/src/app/hero-detail.component.ts', 'HeroDetailComponent');
let annotations = reflector.annotations(HeroDetailComponent);
expect(annotations.length).toEqual(1);
let annotation = annotations[0];
expect(annotation.selector).toEqual('my-hero-detail');
expect(annotation.directives)
.toEqual([
[
reflector.getStaticType(host.resolveModule('angular2/src/common/directives/ng_for'),
'NgFor')
]
]);
});
it('should get and empty annotation list for an unknown class', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
let UnknownClass = reflector.getStaticType('/src/app/app.component.ts', 'UnknownClass');
let annotations = reflector.annotations(UnknownClass);
expect(annotations).toEqual([]);
});
it('should get propMetadata for HeroDetailComponent', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
let HeroDetailComponent =
reflector.getStaticType('/src/app/hero-detail.component.ts', 'HeroDetailComponent');
let props = reflector.propMetadata(HeroDetailComponent);
@ -76,254 +86,175 @@ export function main() {
});
it('should get an empty object from propMetadata for an unknown class', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
let UnknownClass = reflector.getStaticType('/src/app/app.component.ts', 'UnknownClass');
let properties = reflector.propMetadata(UnknownClass);
expect(properties).toEqual({});
});
it('should get empty parameters list for an unknown class ', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
let UnknownClass = reflector.getStaticType('/src/app/app.component.ts', 'UnknownClass');
let parameters = reflector.parameters(UnknownClass);
expect(parameters).toEqual([]);
});
it('should simplify primitive into itself', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
expect(reflector.simplify('', 1)).toBe(1);
expect(reflector.simplify('', true)).toBe(true);
expect(reflector.simplify('', "some value")).toBe("some value");
expect(singleModuleSimplify('', 1)).toBe(1);
expect(singleModuleSimplify('', true)).toBe(true);
expect(singleModuleSimplify('', "some value")).toBe("some value");
});
it('should simplify an array into a copy of the array', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
expect(reflector.simplify('', [1, 2, 3])).toEqual([1, 2, 3]);
});
it('should simplify an array into a copy of the array',
() => { expect(singleModuleSimplify('', [1, 2, 3])).toEqual([1, 2, 3]); });
it('should simplify an object to a copy of the object', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
let expr = {a: 1, b: 2, c: 3};
expect(reflector.simplify('', expr)).toEqual(expr);
expect(singleModuleSimplify('', expr)).toEqual(expr);
});
it('should simplify &&', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '&&', left: true, right: true}))).toBe(true);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '&&', left: true, right: false}))).toBe(false);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '&&', left: false, right: true}))).toBe(false);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '&&', left: false, right: false}))).toBe(false);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '&&', left: true, right: true}))).toBe(true);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '&&', left: true, right: false}))).toBe(false);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '&&', left: false, right: true}))).toBe(false);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '&&', left: false, right: false}))).toBe(false);
});
it('should simplify ||', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '||', left: true, right: true}))).toBe(true);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '||', left: true, right: false}))).toBe(true);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '||', left: false, right: true}))).toBe(true);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '||', left: false, right: false}))).toBe(false);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '||', left: true, right: true}))).toBe(true);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '||', left: true, right: false}))).toBe(true);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '||', left: false, right: true}))).toBe(true);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '||', left: false, right: false}))).toBe(false);
});
it('should simplify &', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '&', left: 0x22, right: 0x0F}))).toBe(0x22 & 0x0F);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '&', left: 0x22, right: 0xF0}))).toBe(0x22 & 0xF0);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '&', left: 0x22, right: 0x0F}))).toBe(0x22 & 0x0F);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '&', left: 0x22, right: 0xF0}))).toBe(0x22 & 0xF0);
});
it('should simplify |', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '|', left: 0x22, right: 0x0F}))).toBe(0x22 | 0x0F);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '|', left: 0x22, right: 0xF0}))).toBe(0x22 | 0xF0);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '|', left: 0x22, right: 0x0F}))).toBe(0x22 | 0x0F);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '|', left: 0x22, right: 0xF0}))).toBe(0x22 | 0xF0);
});
it('should simplify ^', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '|', left: 0x22, right: 0x0F}))).toBe(0x22 | 0x0F);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '|', left: 0x22, right: 0xF0}))).toBe(0x22 | 0xF0);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '|', left: 0x22, right: 0x0F}))).toBe(0x22 | 0x0F);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '|', left: 0x22, right: 0xF0}))).toBe(0x22 | 0xF0);
});
it('should simplify ==', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '==', left: 0x22, right: 0x22}))).toBe(0x22 == 0x22);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '==', left: 0x22, right: 0xF0}))).toBe(0x22 == 0xF0);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '==', left: 0x22, right: 0x22}))).toBe(0x22 == 0x22);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '==', left: 0x22, right: 0xF0}))).toBe(0x22 == 0xF0);
});
it('should simplify !=', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '!=', left: 0x22, right: 0x22}))).toBe(0x22 != 0x22);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '!=', left: 0x22, right: 0xF0}))).toBe(0x22 != 0xF0);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '!=', left: 0x22, right: 0x22}))).toBe(0x22 != 0x22);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '!=', left: 0x22, right: 0xF0}))).toBe(0x22 != 0xF0);
});
it('should simplify ===', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '===', left: 0x22, right: 0x22}))).toBe(0x22 === 0x22);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '===', left: 0x22, right: 0xF0}))).toBe(0x22 === 0xF0);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '===', left: 0x22, right: 0x22}))).toBe(0x22 === 0x22);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '===', left: 0x22, right: 0xF0}))).toBe(0x22 === 0xF0);
});
it('should simplify !==', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '!==', left: 0x22, right: 0x22}))).toBe(0x22 !== 0x22);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '!==', left: 0x22, right: 0xF0}))).toBe(0x22 !== 0xF0);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '!==', left: 0x22, right: 0x22}))).toBe(0x22 !== 0x22);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '!==', left: 0x22, right: 0xF0}))).toBe(0x22 !== 0xF0);
});
it('should simplify >', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '>', left: 1, right: 1}))).toBe(1 > 1);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '>', left: 1, right: 0}))).toBe(1 > 0);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '>', left: 0, right: 1}))).toBe(0 > 1);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '>', left: 1, right: 1}))).toBe(1 > 1);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '>', left: 1, right: 0}))).toBe(1 > 0);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '>', left: 0, right: 1}))).toBe(0 > 1);
});
it('should simplify >=', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '>=', left: 1, right: 1}))).toBe(1 >= 1);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '>=', left: 1, right: 0}))).toBe(1 >= 0);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '>=', left: 0, right: 1}))).toBe(0 >= 1);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '>=', left: 1, right: 1}))).toBe(1 >= 1);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '>=', left: 1, right: 0}))).toBe(1 >= 0);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '>=', left: 0, right: 1}))).toBe(0 >= 1);
});
it('should simplify <=', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '<=', left: 1, right: 1}))).toBe(1 <= 1);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '<=', left: 1, right: 0}))).toBe(1 <= 0);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '<=', left: 0, right: 1}))).toBe(0 <= 1);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '<=', left: 1, right: 1}))).toBe(1 <= 1);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '<=', left: 1, right: 0}))).toBe(1 <= 0);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '<=', left: 0, right: 1}))).toBe(0 <= 1);
});
it('should simplify <', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '<', left: 1, right: 1}))).toBe(1 < 1);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '<', left: 1, right: 0}))).toBe(1 < 0);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '<', left: 0, right: 1}))).toBe(0 < 1);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '<', left: 1, right: 1}))).toBe(1 < 1);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '<', left: 1, right: 0}))).toBe(1 < 0);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '<', left: 0, right: 1}))).toBe(0 < 1);
});
it('should simplify <<', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '<<', left: 0x55, right: 2}))).toBe(0x55 << 2);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '<<', left: 0x55, right: 2}))).toBe(0x55 << 2);
});
it('should simplify >>', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '>>', left: 0x55, right: 2}))).toBe(0x55 >> 2);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '>>', left: 0x55, right: 2}))).toBe(0x55 >> 2);
});
it('should simplify +', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '+', left: 0x55, right: 2}))).toBe(0x55 + 2);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '+', left: 0x55, right: 2}))).toBe(0x55 + 2);
});
it('should simplify -', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '-', left: 0x55, right: 2}))).toBe(0x55 - 2);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '-', left: 0x55, right: 2}))).toBe(0x55 - 2);
});
it('should simplify *', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '*', left: 0x55, right: 2}))).toBe(0x55 * 2);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '*', left: 0x55, right: 2}))).toBe(0x55 * 2);
});
it('should simplify /', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '/', left: 0x55, right: 2}))).toBe(0x55 / 2);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '/', left: 0x55, right: 2}))).toBe(0x55 / 2);
});
it('should simplify %', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '%', left: 0x55, right: 2}))).toBe(0x55 % 2);
expect(singleModuleSimplify('', ({ __symbolic: 'binop', operator: '%', left: 0x55, right: 2}))).toBe(0x55 % 2);
});
it('should simplify prefix -', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
expect(reflector.simplify('', ({ __symbolic: 'pre', operator: '-', operand: 2}))).toBe(-2);
expect(singleModuleSimplify('', ({ __symbolic: 'pre', operator: '-', operand: 2}))).toBe(-2);
});
it('should simplify prefix ~', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
expect(reflector.simplify('', ({ __symbolic: 'pre', operator: '~', operand: 2}))).toBe(~2);
expect(singleModuleSimplify('', ({ __symbolic: 'pre', operator: '~', operand: 2}))).toBe(~2);
});
it('should simplify prefix !', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
expect(reflector.simplify('', ({ __symbolic: 'pre', operator: '!', operand: true}))).toBe(!true);
expect(reflector.simplify('', ({ __symbolic: 'pre', operator: '!', operand: false}))).toBe(!false);
expect(singleModuleSimplify('', ({ __symbolic: 'pre', operator: '!', operand: true}))).toBe(!true);
expect(singleModuleSimplify('', ({ __symbolic: 'pre', operator: '!', operand: false}))).toBe(!false);
});
it('should simplify an array index', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
expect(reflector.simplify('', ({__symbolic: "index", expression: [1, 2, 3], index: 2})))
expect(singleModuleSimplify('', ({__symbolic: "index", expression: [1, 2, 3], index: 2})))
.toBe(3);
});
it('should simplify an object index', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
let expr = {__symbolic: "select", expression: {a: 1, b: 2, c: 3}, member: "b"};
expect(reflector.simplify('', expr)).toBe(2);
expect(singleModuleSimplify('', expr)).toBe(2);
});
it('should simplify a module reference', () => {
let host = new MockReflectorHost();
let reflector = new StaticReflector(host);
expect(reflector.simplify('/src/cases',
({__symbolic: "reference", module: "./extern", name: "s"})))
it('should simplify a module reference across modules', () => {
expect(crossModuleSimplify('/src/cases',
({__symbolic: "reference", module: "./extern", name: "s"})))
.toEqual("s");
});
it('should simplify a module reference without crossing modules', () => {
expect(singleModuleSimplify('/src/cases',
({__symbolic: "reference", module: "./extern", name: "s"})))
.toEqual(reflector.getStaticType('/src/extern.d.ts', 's'));
});
});
}
class MockReflectorHost implements StaticReflectorHost {
// In tests, assume that symbols are not re-exported
findDeclaration(modulePath: string,
symbolName: string): {declarationPath: string, declaredName: string} {
return {declarationPath: modulePath, declaredName: symbolName};
}
resolveModule(moduleName: string, containingFile?: string): string {
function splitPath(path: string): string[] { return path.split(/\/|\\/g); }
@ -363,68 +294,80 @@ class MockReflectorHost implements StaticReflectorHost {
getMetadataFor(moduleId: string): any {
return {
'/tmp/angular2/src/common/directives/ng_for.d.ts':
'/tmp/angular2/src/common/forms/directives.d.ts':
{
"__symbolic": "module",
"metadata":
"metadata": {
"FORM_DIRECTIVES": [
{
"NgFor":
{
"__symbolic": "class",
"decorators":
[
{
"__symbolic": "call",
"expression": {
"__symbolic": "reference",
"name": "Directive",
"module": "../../core/metadata"
},
"arguments":
[
"__symbolic": "reference",
"name": "NgFor",
"module": "angular2/src/common/directives/ng_for"
}
]
}
},
'/tmp/angular2/src/common/directives/ng_for.d.ts':
{
"__symbolic": "module",
"metadata":
{
"NgFor":
{
"__symbolic": "class",
"decorators":
[
{
"__symbolic": "call",
"expression": {
"__symbolic": "reference",
"name": "Directive",
"module": "../../core/metadata"
},
"arguments": [
{
"selector": "[ngFor][ngForOf]",
"inputs": ["ngForTrackBy", "ngForOf", "ngForTemplate"]
}
]
}
],
"members":
{
"__ctor__": [
}
],
"members":
{
"__symbolic": "constructor",
"parameters":
[
{
"__symbolic": "reference",
"module": "../../core/linker/view_container_ref",
"name": "ViewContainerRef"
},
{
"__symbolic": "reference",
"module": "../../core/linker/template_ref",
"name": "TemplateRef"
},
{
"__symbolic": "reference",
"module":
"../../core/change_detection/differs/iterable_differs",
"name": "IterableDiffers"
},
{
"__symbolic": "reference",
"module":
"../../core/change_detection/change_detector_ref",
"name": "ChangeDetectorRef"
}
]
"__ctor__": [
{
"__symbolic": "constructor",
"parameters":
[
{
"__symbolic": "reference",
"module": "../../core/linker/view_container_ref",
"name": "ViewContainerRef"
},
{
"__symbolic": "reference",
"module": "../../core/linker/template_ref",
"name": "TemplateRef"
},
{
"__symbolic": "reference",
"module":
"../../core/change_detection/differs/iterable_differs",
"name": "IterableDiffers"
},
{
"__symbolic": "reference",
"module":
"../../core/change_detection/change_detector_ref",
"name": "ChangeDetectorRef"
}
]
}
]
}
]
}
}
}
},
}
}
},
'/tmp/angular2/src/core/linker/view_container_ref.d.ts':
{"metadata": {"ViewContainerRef": {"__symbolic": "class"}}},
'/tmp/angular2/src/core/linker/template_ref.d.ts':
@ -453,7 +396,15 @@ class MockReflectorHost implements StaticReflectorHost {
"arguments": [
{
"selector": "my-hero-detail",
"template": "\n <div *ngIf=\"hero\">\n <h2>{{hero.name}} details!</h2>\n <div><label>id: </label>{{hero.id}}</div>\n <div>\n <label>name: </label>\n <input [(ngModel)]=\"hero.name\" placeholder=\"name\"/>\n </div>\n </div>\n"
"template": "\n <div *ngIf=\"hero\">\n <h2>{{hero.name}} details!</h2>\n <div><label>id: </label>{{hero.id}}</div>\n <div>\n <label>name: </label>\n <input [(ngModel)]=\"hero.name\" placeholder=\"name\"/>\n </div>\n </div>\n",
"directives":
[
{
"__symbolic": "reference",
"name": "FORM_DIRECTIVES",
"module": "angular2/src/common/forms/directives"
}
]
}
]
}