fix(compiler): look for flat module resources using declaration module path (#15367)

`ngc` would look for flat module resources relative to the flat module index.
`ngc` now looks for flat module resources relative to the `.d.ts` file that declarates
the component.

Fixes #15221

PR Close #15367
This commit is contained in:
Chuck Jazdzewski
2017-03-20 16:31:11 -07:00
committed by Miško Hevery
parent 7354949763
commit 90d2518d9a
19 changed files with 311 additions and 17 deletions

View File

@ -42,6 +42,7 @@ export class StaticAndDynamicReflectionCapabilities {
setter(name: string): ɵSetterFn { return this.dynamicDelegate.setter(name); }
method(name: string): ɵMethodFn { return this.dynamicDelegate.method(name); }
importUri(type: any): string { return this.staticDelegate.importUri(type); }
resourceUri(type: any): string { return this.staticDelegate.resourceUri(type); }
resolveIdentifier(name: string, moduleUrl: string, members: string[], runtime: any) {
return this.staticDelegate.resolveIdentifier(name, moduleUrl, members);
}

View File

@ -54,6 +54,11 @@ export class StaticReflector implements ɵReflectorReader {
return staticSymbol ? staticSymbol.filePath : null;
}
resourceUri(typeOrFunc: StaticSymbol): string {
const staticSymbol = this.findSymbolDeclaration(typeOrFunc);
return this.symbolResolver.getResourcePath(staticSymbol);
}
resolveIdentifier(name: string, moduleUrl: string, members: string[]): StaticSymbol {
const importSymbol = this.getStaticSymbol(moduleUrl, name);
const rootSymbol = this.findDeclaration(moduleUrl, name);

View File

@ -58,6 +58,7 @@ export class StaticSymbolResolver {
private resolvedFilePaths = new Set<string>();
// Note: this will only contain StaticSymbols without members!
private importAs = new Map<StaticSymbol, StaticSymbol>();
private symbolResourcePaths = new Map<StaticSymbol, string>();
constructor(
private host: StaticSymbolResolverHost, private staticSymbolCache: StaticSymbolCache,
@ -108,6 +109,15 @@ export class StaticSymbolResolver {
return result;
}
/**
* getResourcePath produces the path to the original location of the symbol and should
* be used to determine the relative location of resource references recorded in
* symbol metadata.
*/
getResourcePath(staticSymbol: StaticSymbol): string {
return this.symbolResourcePaths.get(staticSymbol) || staticSymbol.filePath;
}
/**
* getTypeArity returns the number of generic type parameters the given symbol
* has. If the symbol is not a type the result is null.
@ -200,18 +210,35 @@ export class StaticSymbolResolver {
// handle direct declarations of the symbol
const topLevelSymbolNames =
new Set<string>(Object.keys(metadata['metadata']).map(unescapeIdentifier));
const origins: {[index: string]: string} = metadata['origins'] || {};
Object.keys(metadata['metadata']).forEach((metadataKey) => {
const symbolMeta = metadata['metadata'][metadataKey];
const name = unescapeIdentifier(metadataKey);
const canonicalSymbol = this.getStaticSymbol(filePath, name);
const symbol = this.getStaticSymbol(filePath, name);
let importSymbol: StaticSymbol|undefined = undefined;
if (metadata['importAs']) {
// Index bundle indexes should use the importAs module name instead of a reference
// to the .d.ts file directly.
const importSymbol = this.getStaticSymbol(metadata['importAs'], name);
this.recordImportAs(canonicalSymbol, importSymbol);
importSymbol = this.getStaticSymbol(metadata['importAs'], name);
this.recordImportAs(symbol, importSymbol);
}
const origin = origins[metadataKey];
if (origin) {
// If the symbol is from a bundled index, use the declaration location of the
// symbol so relative references (such as './my.html') will be calculated
// correctly.
const originFilePath = this.resolveModule(origin, filePath);
if (!originFilePath) {
this.reportError(
new Error(`Couldn't resolve original symbol for ${origin} from ${filePath}`), null);
} else {
this.symbolResourcePaths.set(symbol, originFilePath);
}
}
resolvedSymbols.push(
this.createResolvedSymbol(canonicalSymbol, topLevelSymbolNames, symbolMeta));
this.createResolvedSymbol(symbol, filePath, topLevelSymbolNames, symbolMeta));
});
}
@ -257,7 +284,7 @@ export class StaticSymbolResolver {
}
private createResolvedSymbol(
sourceSymbol: StaticSymbol, topLevelSymbolNames: Set<string>,
sourceSymbol: StaticSymbol, topLevelPath: string, topLevelSymbolNames: Set<string>,
metadata: any): ResolvedStaticSymbol {
const self = this;
@ -291,7 +318,7 @@ export class StaticSymbolResolver {
return {__symbolic: 'reference', name: name};
} else {
if (topLevelSymbolNames.has(name)) {
return self.getStaticSymbol(sourceSymbol.filePath, name);
return self.getStaticSymbol(topLevelPath, name);
}
// ambient value
null;

View File

@ -1060,7 +1060,7 @@ function isValidType(value: any): boolean {
export function componentModuleUrl(
reflector: ɵReflectorReader, type: Type<any>, cmpMetadata: Component): string {
if (type instanceof StaticSymbol) {
return type.filePath;
return reflector.resourceUri(type);
}
const moduleId = cmpMetadata.moduleId;