fix(metadata): Do not attach module names to metadata.
The filename contains the module name as resolved by users, so the top-level module name is uneeded. Module names on references are replaced by capturing the import syntax from the module. This allows readers of the metadata to do the module resolution themselves. Fixes #8225 Fixes #8082 Closes #8256
This commit is contained in:
@ -1,12 +1,8 @@
|
||||
import {ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||
import {StringMapWrapper} from 'angular2/src/facade/collection';
|
||||
import {
|
||||
isArray,
|
||||
isBlank,
|
||||
isNumber,
|
||||
isPresent,
|
||||
isPrimitive,
|
||||
isString,
|
||||
Type
|
||||
} from 'angular2/src/facade/lang';
|
||||
import {
|
||||
AttributeMetadata,
|
||||
@ -35,13 +31,19 @@ import {ReflectorReader} from 'angular2/src/core/reflection/reflector_reader';
|
||||
*/
|
||||
export interface StaticReflectorHost {
|
||||
/**
|
||||
* Return a ModuleMetadata for the give module.
|
||||
* Return a ModuleMetadata for the given module.
|
||||
*
|
||||
* @param moduleId is a string identifier for a module in the form that would expected in a
|
||||
* module import of an import statement.
|
||||
* @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};
|
||||
|
||||
/**
|
||||
* Resolve a module from an import statement form to an absolute path.
|
||||
* @param moduleName the location imported from
|
||||
* @param containingFile for relative imports, the path of the file containing the import
|
||||
*/
|
||||
resolveModule(moduleName: string, containingFile?: string): string;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -68,10 +70,10 @@ export class StaticReflector implements ReflectorReader {
|
||||
importUri(typeOrFunc: any): string { return (<StaticType>typeOrFunc).moduleId; }
|
||||
|
||||
/**
|
||||
* getStatictype produces a Type whose metadata is known but whose implementation is not loaded.
|
||||
* 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 would be passed to an import statement.
|
||||
* @param moduleId the module identifier as an absolute path.
|
||||
* @param name the name of the type.
|
||||
*/
|
||||
public getStaticType(moduleId: string, name: string): StaticType {
|
||||
@ -137,7 +139,7 @@ export class StaticReflector implements ReflectorReader {
|
||||
|
||||
private conversionMap = new Map<StaticType, (moduleContext: string, expression: any) => any>();
|
||||
private initializeConversionMap(): any {
|
||||
let core_metadata = 'angular2/src/core/metadata';
|
||||
let core_metadata = this.host.resolveModule('angular2/src/core/metadata');
|
||||
let conversionMap = this.conversionMap;
|
||||
conversionMap.set(this.getStaticType(core_metadata, 'Directive'),
|
||||
(moduleContext, expression) => {
|
||||
@ -272,7 +274,7 @@ export class StaticReflector implements ReflectorReader {
|
||||
if (isMetadataSymbolicCallExpression(expression)) {
|
||||
let target = expression['expression'];
|
||||
if (isMetadataSymbolicReferenceExpression(target)) {
|
||||
let moduleId = this.normalizeModuleName(moduleContext, target['module']);
|
||||
let moduleId = this.host.resolveModule(target['module'], moduleContext);
|
||||
return this.getStaticType(moduleId, target['name']);
|
||||
}
|
||||
}
|
||||
@ -417,7 +419,7 @@ export class StaticReflector implements ReflectorReader {
|
||||
return null;
|
||||
case "reference":
|
||||
let referenceModuleName =
|
||||
_this.normalizeModuleName(moduleContext, expression['module']);
|
||||
_this.host.resolveModule(expression['module'], moduleContext);
|
||||
let referenceModule = _this.getModuleMetadata(referenceModuleName);
|
||||
let referenceValue = referenceModule['metadata'][expression['name']];
|
||||
if (isClassMetadata(referenceValue)) {
|
||||
@ -440,6 +442,9 @@ export class StaticReflector implements ReflectorReader {
|
||||
return simplify(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param module an absolute path to a module file.
|
||||
*/
|
||||
public getModuleMetadata(module: string): {[key: string]: any} {
|
||||
let moduleMetadata = this.metadataCache.get(module);
|
||||
if (!isPresent(moduleMetadata)) {
|
||||
@ -460,13 +465,6 @@ export class StaticReflector implements ReflectorReader {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private normalizeModuleName(from: string, to: string): string {
|
||||
if (to.startsWith('.')) {
|
||||
return pathTo(from, to);
|
||||
}
|
||||
return to;
|
||||
}
|
||||
}
|
||||
|
||||
function isMetadataSymbolicCallExpression(expression: any): boolean {
|
||||
@ -481,35 +479,3 @@ function isMetadataSymbolicReferenceExpression(expression: any): boolean {
|
||||
function isClassMetadata(expression: any): boolean {
|
||||
return !isPrimitive(expression) && !isArray(expression) && expression['__symbolic'] == 'class';
|
||||
}
|
||||
|
||||
function splitPath(path: string): string[] {
|
||||
return path.split(/\/|\\/g);
|
||||
}
|
||||
|
||||
function resolvePath(pathParts: string[]): string {
|
||||
let result = [];
|
||||
ListWrapper.forEachWithIndex(pathParts, (part, index) => {
|
||||
switch (part) {
|
||||
case '':
|
||||
case '.':
|
||||
if (index > 0) return;
|
||||
break;
|
||||
case '..':
|
||||
if (index > 0 && result.length != 0) result.pop();
|
||||
return;
|
||||
}
|
||||
result.push(part);
|
||||
});
|
||||
return result.join('/');
|
||||
}
|
||||
|
||||
function pathTo(from: string, to: string): string {
|
||||
let result = to;
|
||||
if (to.startsWith('.')) {
|
||||
let fromParts = splitPath(from);
|
||||
fromParts.pop(); // remove the file name.
|
||||
let toParts = splitPath(to);
|
||||
result = resolvePath(fromParts.concat(toParts));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
Reference in New Issue
Block a user