Skip to content

Commit d91ff17

Browse files
chuckjazalxhub
authored andcommitted
fix(compiler): generate the correct imports for summary type-check
Summaries should be ignored when importing the types used in a type-check block.
1 parent d213a20 commit d91ff17

File tree

5 files changed

+66
-41
lines changed

5 files changed

+66
-41
lines changed

packages/compiler-cli/test/test_support.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import * as path from 'path';
1212
import * as ts from 'typescript';
1313
import * as ng from '../index';
1414

15+
// TEST_TMPDIR is set by bazel.
1516
const tmpdir = process.env.TEST_TMPDIR || os.tmpdir();
1617

1718
function getNgRootDir() {
@@ -21,16 +22,19 @@ function getNgRootDir() {
2122
}
2223

2324
export function writeTempFile(name: string, contents: string): string {
24-
// TEST_TMPDIR is set by bazel.
2525
const id = (Math.random() * 1000000).toFixed(0);
2626
const fn = path.join(tmpdir, `tmp.${id}.${name}`);
2727
fs.writeFileSync(fn, contents);
2828
return fn;
2929
}
3030

3131
export function makeTempDir(): string {
32-
const id = (Math.random() * 1000000).toFixed(0);
33-
const dir = path.join(tmpdir, `tmp.${id}`);
32+
let dir: string;
33+
while (true) {
34+
const id = (Math.random() * 1000000).toFixed(0);
35+
dir = path.join(tmpdir, `tmp.${id}`);
36+
if (!fs.existsSync(dir)) break;
37+
}
3438
fs.mkdirSync(dir);
3539
return dir;
3640
}

packages/compiler/src/aot/compiler.ts

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -218,15 +218,14 @@ export class AotCompiler {
218218

219219
const externalReferenceVars = new Map<any, string>();
220220
externalReferences.forEach((ref, typeIndex) => {
221-
if (this._host.isSourceFile(ref.filePath)) {
222-
externalReferenceVars.set(ref, `_decl${ngModuleIndex}_${typeIndex}`);
223-
}
221+
externalReferenceVars.set(ref, `_decl${ngModuleIndex}_${typeIndex}`);
224222
});
225223
externalReferenceVars.forEach((varName, reference) => {
226224
outputCtx.statements.push(
227225
o.variable(varName)
228226
.set(o.NULL_EXPR.cast(o.DYNAMIC_TYPE))
229-
.toDeclStmt(o.expressionType(outputCtx.importExpr(reference))));
227+
.toDeclStmt(o.expressionType(outputCtx.importExpr(
228+
reference, /* typeParams */ null, /* useSummaries */ false))));
230229
});
231230

232231
if (emitFlags & StubEmitFlags.TypeCheck) {
@@ -515,35 +514,38 @@ export class AotCompiler {
515514
}
516515

517516
private _createOutputContext(genFilePath: string): OutputContext {
518-
const importExpr = (symbol: StaticSymbol, typeParams: o.Type[] | null = null) => {
519-
if (!(symbol instanceof StaticSymbol)) {
520-
throw new Error(`Internal error: unknown identifier ${JSON.stringify(symbol)}`);
521-
}
522-
const arity = this._symbolResolver.getTypeArity(symbol) || 0;
523-
const {filePath, name, members} = this._symbolResolver.getImportAs(symbol) || symbol;
524-
const importModule = this._fileNameToModuleName(filePath, genFilePath);
525-
526-
// It should be good enough to compare filePath to genFilePath and if they are equal
527-
// there is a self reference. However, ngfactory files generate to .ts but their
528-
// symbols have .d.ts so a simple compare is insufficient. They should be canonical
529-
// and is tracked by #17705.
530-
const selfReference = this._fileNameToModuleName(genFilePath, genFilePath);
531-
const moduleName = importModule === selfReference ? null : importModule;
532-
533-
// If we are in a type expression that refers to a generic type then supply
534-
// the required type parameters. If there were not enough type parameters
535-
// supplied, supply any as the type. Outside a type expression the reference
536-
// should not supply type parameters and be treated as a simple value reference
537-
// to the constructor function itself.
538-
const suppliedTypeParams = typeParams || [];
539-
const missingTypeParamsCount = arity - suppliedTypeParams.length;
540-
const allTypeParams =
541-
suppliedTypeParams.concat(new Array(missingTypeParamsCount).fill(o.DYNAMIC_TYPE));
542-
return members.reduce(
543-
(expr, memberName) => expr.prop(memberName),
544-
<o.Expression>o.importExpr(
545-
new o.ExternalReference(moduleName, name, null), allTypeParams));
546-
};
517+
const importExpr =
518+
(symbol: StaticSymbol, typeParams: o.Type[] | null = null,
519+
useSummaries: boolean = true) => {
520+
if (!(symbol instanceof StaticSymbol)) {
521+
throw new Error(`Internal error: unknown identifier ${JSON.stringify(symbol)}`);
522+
}
523+
const arity = this._symbolResolver.getTypeArity(symbol) || 0;
524+
const {filePath, name, members} =
525+
this._symbolResolver.getImportAs(symbol, useSummaries) || symbol;
526+
const importModule = this._fileNameToModuleName(filePath, genFilePath);
527+
528+
// It should be good enough to compare filePath to genFilePath and if they are equal
529+
// there is a self reference. However, ngfactory files generate to .ts but their
530+
// symbols have .d.ts so a simple compare is insufficient. They should be canonical
531+
// and is tracked by #17705.
532+
const selfReference = this._fileNameToModuleName(genFilePath, genFilePath);
533+
const moduleName = importModule === selfReference ? null : importModule;
534+
535+
// If we are in a type expression that refers to a generic type then supply
536+
// the required type parameters. If there were not enough type parameters
537+
// supplied, supply any as the type. Outside a type expression the reference
538+
// should not supply type parameters and be treated as a simple value reference
539+
// to the constructor function itself.
540+
const suppliedTypeParams = typeParams || [];
541+
const missingTypeParamsCount = arity - suppliedTypeParams.length;
542+
const allTypeParams =
543+
suppliedTypeParams.concat(new Array(missingTypeParamsCount).fill(o.DYNAMIC_TYPE));
544+
return members.reduce(
545+
(expr, memberName) => expr.prop(memberName),
546+
<o.Expression>o.importExpr(
547+
new o.ExternalReference(moduleName, name, null), allTypeParams));
548+
};
547549

548550
return {statements: [], genFilePath, importExpr};
549551
}

packages/compiler/src/aot/static_symbol_resolver.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,10 @@ export class StaticSymbolResolver {
9898
*
9999
* @param staticSymbol the symbol for which to generate a import symbol
100100
*/
101-
getImportAs(staticSymbol: StaticSymbol): StaticSymbol|null {
101+
getImportAs(staticSymbol: StaticSymbol, useSummaries: boolean = true): StaticSymbol|null {
102102
if (staticSymbol.members.length) {
103103
const baseSymbol = this.getStaticSymbol(staticSymbol.filePath, staticSymbol.name);
104-
const baseImportAs = this.getImportAs(baseSymbol);
104+
const baseImportAs = this.getImportAs(baseSymbol, useSummaries);
105105
return baseImportAs ?
106106
this.getStaticSymbol(baseImportAs.filePath, baseImportAs.name, staticSymbol.members) :
107107
null;
@@ -111,14 +111,14 @@ export class StaticSymbolResolver {
111111
const summarizedName = stripSummaryForJitNameSuffix(staticSymbol.name);
112112
const baseSymbol =
113113
this.getStaticSymbol(summarizedFileName, summarizedName, staticSymbol.members);
114-
const baseImportAs = this.getImportAs(baseSymbol);
114+
const baseImportAs = this.getImportAs(baseSymbol, useSummaries);
115115
return baseImportAs ?
116116
this.getStaticSymbol(
117117
summaryForJitFileName(baseImportAs.filePath), summaryForJitName(baseImportAs.name),
118118
baseSymbol.members) :
119119
null;
120120
}
121-
let result = this.summaryResolver.getImportAs(staticSymbol);
121+
let result = (useSummaries && this.summaryResolver.getImportAs(staticSymbol)) || null;
122122
if (!result) {
123123
result = this.importAs.get(staticSymbol) !;
124124
}

packages/compiler/src/util.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ export function utf8Encode(str: string): string {
152152
export interface OutputContext {
153153
genFilePath: string;
154154
statements: o.Statement[];
155-
importExpr(reference: any, typeParams?: o.Type[]|null): o.Expression;
155+
importExpr(reference: any, typeParams?: o.Type[]|null, useSummaries?: boolean): o.Expression;
156156
}
157157

158158
export function stringify(token: any): string {

packages/compiler/test/aot/static_symbol_resolver_spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,25 @@ describe('StaticSymbolResolver', () => {
196196
.toBe(symbolCache.get('/test3.d.ts', 'b'));
197197
});
198198

199+
it('should ignore summaries for inputAs if requested', () => {
200+
init(
201+
{
202+
'/test.ts': `
203+
export {a} from './test2';
204+
`
205+
},
206+
[], [{
207+
symbol: symbolCache.get('/test2.d.ts', 'a'),
208+
importAs: symbolCache.get('/test3.d.ts', 'b')
209+
}]);
210+
211+
symbolResolver.getSymbolsOf('/test.ts');
212+
213+
expect(
214+
symbolResolver.getImportAs(symbolCache.get('/test2.d.ts', 'a'), /* useSummaries */ false))
215+
.toBeUndefined();
216+
});
217+
199218
it('should calculate importAs for symbols with members based on importAs for symbols without',
200219
() => {
201220
init(

0 commit comments

Comments
 (0)