fix(compiler): don’t reexport types in .ngfactory
files (#18788)
This is needed as the typescript no longer elides type reexports in the generated code when using transformers. A nice side effect is that this make summaries shorter and produces less reexports as we rollup reexports. PR Close #18788
This commit is contained in:

committed by
Miško Hevery

parent
f83b819bea
commit
8c858d76dd
@ -6,14 +6,14 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {GeneratedFile, toTypeScript} from '@angular/compiler';
|
||||
import {AotSummaryResolver, GeneratedFile, StaticSymbolCache, StaticSymbolResolver, toTypeScript} from '@angular/compiler';
|
||||
import {NodeFlags} from '@angular/core/src/view/index';
|
||||
import {MetadataBundler, privateEntriesToIndex} from '@angular/tsc-wrapped';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {extractSourceMap, originalPositionFor} from '../output/source_map_util';
|
||||
|
||||
import {EmittingCompilerHost, MockDirectory, MockMetadataBundlerHost, arrayToMockDir, compile, expectNoDiagnostics, settings, setup, toMockFileArray} from './test_util';
|
||||
import {EmittingCompilerHost, MockAotCompilerHost, MockCompilerHost, MockDirectory, MockMetadataBundlerHost, arrayToMockDir, compile, expectNoDiagnostics, settings, setup, toMockFileArray} from './test_util';
|
||||
|
||||
describe('compiler (unbundled Angular)', () => {
|
||||
let angularFiles = setup();
|
||||
@ -458,12 +458,43 @@ describe('compiler (unbundled Angular)', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('inheritance with summaries', () => {
|
||||
describe('summaries', () => {
|
||||
let angularSummaryFiles: MockDirectory;
|
||||
beforeEach(() => {
|
||||
beforeAll(() => {
|
||||
angularSummaryFiles = compile(angularFiles, {useSummaries: false, emit: true}).outDir;
|
||||
});
|
||||
|
||||
inheritanceWithSummariesSpecs(() => angularSummaryFiles);
|
||||
|
||||
it('should not reexport type symbols mentioned in constructors', () => {
|
||||
const libInput: MockDirectory = {
|
||||
'lib': {
|
||||
'base.ts': `
|
||||
export type AType = {};
|
||||
|
||||
export class AClass {
|
||||
constructor(a: AType) {}
|
||||
}
|
||||
`
|
||||
}
|
||||
};
|
||||
const appInput: MockDirectory = {
|
||||
'app': {
|
||||
'main.ts': `
|
||||
export * from '../lib/base';
|
||||
`
|
||||
}
|
||||
};
|
||||
|
||||
const {outDir: libOutDir} = compile([libInput, angularSummaryFiles], {useSummaries: true});
|
||||
const {genFiles: appGenFiles} =
|
||||
compile([appInput, libOutDir, angularSummaryFiles], {useSummaries: true});
|
||||
const appNgFactory = appGenFiles.find((f) => f.genFileUrl === '/app/main.ngfactory.ts');
|
||||
expect(toTypeScript(appNgFactory)).not.toContain('AType');
|
||||
});
|
||||
});
|
||||
|
||||
function inheritanceWithSummariesSpecs(getAngularSummaryFiles: () => MockDirectory) {
|
||||
function compileParentAndChild(
|
||||
{parentClassDecorator, parentModuleDecorator, childClassDecorator, childModuleDecorator}: {
|
||||
parentClassDecorator: string,
|
||||
@ -499,8 +530,10 @@ describe('compiler (unbundled Angular)', () => {
|
||||
}
|
||||
};
|
||||
|
||||
const {outDir: libOutDir} = compile([libInput, angularSummaryFiles], {useSummaries: true});
|
||||
const {genFiles} = compile([libOutDir, appInput, angularSummaryFiles], {useSummaries: true});
|
||||
const {outDir: libOutDir} =
|
||||
compile([libInput, getAngularSummaryFiles()], {useSummaries: true});
|
||||
const {genFiles} =
|
||||
compile([libOutDir, appInput, getAngularSummaryFiles()], {useSummaries: true});
|
||||
return genFiles.find(gf => gf.srcFileUrl === '/app/main.ts');
|
||||
}
|
||||
|
||||
@ -534,8 +567,10 @@ describe('compiler (unbundled Angular)', () => {
|
||||
}
|
||||
};
|
||||
|
||||
const {outDir: libOutDir} = compile([libInput, angularSummaryFiles], {useSummaries: true});
|
||||
const {genFiles} = compile([libOutDir, appInput, angularSummaryFiles], {useSummaries: true});
|
||||
const {outDir: libOutDir} =
|
||||
compile([libInput, getAngularSummaryFiles()], {useSummaries: true});
|
||||
const {genFiles} =
|
||||
compile([libOutDir, appInput, getAngularSummaryFiles()], {useSummaries: true});
|
||||
const mainNgFactory = genFiles.find(gf => gf.srcFileUrl === '/app/main.ts');
|
||||
const flags = NodeFlags.TypeDirective | NodeFlags.Component | NodeFlags.OnDestroy;
|
||||
expect(toTypeScript(mainNgFactory))
|
||||
@ -584,11 +619,11 @@ describe('compiler (unbundled Angular)', () => {
|
||||
}
|
||||
};
|
||||
const {outDir: lib1OutDir} =
|
||||
compile([lib1Input, angularSummaryFiles], {useSummaries: true});
|
||||
compile([lib1Input, getAngularSummaryFiles()], {useSummaries: true});
|
||||
const {outDir: lib2OutDir} =
|
||||
compile([lib1OutDir, lib2Input, angularSummaryFiles], {useSummaries: true});
|
||||
compile([lib1OutDir, lib2Input, getAngularSummaryFiles()], {useSummaries: true});
|
||||
const {genFiles} =
|
||||
compile([lib2OutDir, appInput, angularSummaryFiles], {useSummaries: true});
|
||||
compile([lib2OutDir, appInput, getAngularSummaryFiles()], {useSummaries: true});
|
||||
const mainNgFactory = genFiles.find(gf => gf.srcFileUrl === '/app/main.ts');
|
||||
const flags = NodeFlags.TypeDirective | NodeFlags.Component | NodeFlags.OnDestroy;
|
||||
expect(toTypeScript(mainNgFactory))
|
||||
@ -714,7 +749,7 @@ describe('compiler (unbundled Angular)', () => {
|
||||
'Please add a NgModule decorator to the class.');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('compiler (bundled Angular)', () => {
|
||||
|
@ -108,7 +108,12 @@ export function main() {
|
||||
() => {
|
||||
init();
|
||||
const externalSerialized = serializeSummaries(
|
||||
'someFile.ts', createMockOutputContext(), summaryResolver, symbolResolver, [], [
|
||||
'someFile.ts', createMockOutputContext(), summaryResolver, symbolResolver,
|
||||
[
|
||||
{symbol: symbolCache.get('/tmp/external.ts', 'SomeExternalPipe'), metadata: null},
|
||||
{symbol: symbolCache.get('/tmp/external.ts', 'SomeExternalDir'), metadata: null},
|
||||
],
|
||||
[
|
||||
{
|
||||
summary: {
|
||||
summaryKind: CompileSummaryKind.Pipe,
|
||||
@ -135,7 +140,11 @@ export function main() {
|
||||
});
|
||||
|
||||
const serialized = serializeSummaries(
|
||||
'someFile.ts', createMockOutputContext(), summaryResolver, symbolResolver, [], [{
|
||||
'someFile.ts', createMockOutputContext(), summaryResolver, symbolResolver,
|
||||
[
|
||||
{symbol: symbolCache.get('/tmp/some_module.ts', 'SomeModule'), metadata: null},
|
||||
],
|
||||
[{
|
||||
summary: <any>{
|
||||
summaryKind: CompileSummaryKind.NgModule,
|
||||
type: {reference: symbolCache.get('/tmp/some_module.ts', 'SomeModule')},
|
||||
@ -152,15 +161,42 @@ export function main() {
|
||||
},
|
||||
metadata: null as any
|
||||
}]);
|
||||
|
||||
const summaries =
|
||||
deserializeSummaries(symbolCache, summaryResolver, 'someFile.d.ts', serialized.json)
|
||||
.summaries;
|
||||
init({
|
||||
'/tmp/some_module.ngsummary.json': serialized.json,
|
||||
});
|
||||
|
||||
const serializedReexport = serializeSummaries(
|
||||
'someFile.ts', createMockOutputContext(), summaryResolver, symbolResolver,
|
||||
[
|
||||
{
|
||||
symbol: symbolCache.get('/tmp/some_reexport.ts', 'ReexportModule'),
|
||||
metadata: symbolCache.get('/tmp/some_module.d.ts', 'SomeModule')
|
||||
},
|
||||
],
|
||||
[]);
|
||||
|
||||
expect(summaries.length).toBe(3);
|
||||
expect(summaries[0].symbol).toBe(symbolCache.get('/tmp/some_module.d.ts', 'SomeModule'));
|
||||
expect(summaries[1].symbol).toBe(symbolCache.get('/tmp/external.d.ts', 'SomeExternalDir'));
|
||||
expect(summaries[2].symbol)
|
||||
.toBe(symbolCache.get('/tmp/external.d.ts', 'SomeExternalPipe'));
|
||||
|
||||
const reexportSummaries =
|
||||
deserializeSummaries(
|
||||
symbolCache, summaryResolver, 'someFile.d.ts', serializedReexport.json)
|
||||
.summaries;
|
||||
expect(reexportSummaries.length).toBe(4);
|
||||
expect(reexportSummaries[0].symbol)
|
||||
.toBe(symbolCache.get('/tmp/some_reexport.d.ts', 'ReexportModule'));
|
||||
expect(reexportSummaries[1].symbol)
|
||||
.toBe(symbolCache.get('/tmp/some_module.d.ts', 'SomeModule'));
|
||||
expect(reexportSummaries[2].symbol)
|
||||
.toBe(symbolCache.get('/tmp/external.d.ts', 'SomeExternalDir'));
|
||||
expect(reexportSummaries[3].symbol)
|
||||
.toBe(symbolCache.get('/tmp/external.d.ts', 'SomeExternalPipe'));
|
||||
});
|
||||
|
||||
it('should automatically add the metadata of referenced symbols that are not in the source files',
|
||||
@ -176,6 +212,16 @@ export function main() {
|
||||
{
|
||||
symbol: symbolCache.get('/tmp/external_svc.ts', 'SomeService'),
|
||||
metadata: {__symbolic: 'class'}
|
||||
},
|
||||
// Note: This is an important usecase when using ng1 and ng2 together via
|
||||
// goog.module.
|
||||
// In these cases, users write the following to get a referrable symbol in metadata
|
||||
// collection:
|
||||
// import UsernameService from 'goog:somePackage.UsernameService';
|
||||
// export {UsernameService};
|
||||
{
|
||||
symbol: symbolCache.get('/tmp/external.ts', 'ReexportNonExistent'),
|
||||
metadata: symbolCache.get('/tmp/external.ts', 'NonExistent'),
|
||||
}
|
||||
],
|
||||
[{
|
||||
@ -204,7 +250,8 @@ export function main() {
|
||||
metadata: {
|
||||
local: symbolCache.get('/tmp/local.ts', 'local'),
|
||||
external: symbolCache.get('/tmp/external.d.ts', 'PROVIDERS'),
|
||||
externalNonSummary: symbolCache.get('/tmp/non_summary.d.ts', 'external')
|
||||
externalNonSummary: symbolCache.get('/tmp/non_summary.d.ts', 'external'),
|
||||
reexportNonExistent: symbolCache.get('/tmp/external.ts', 'ReexportNonExistent'),
|
||||
}
|
||||
}],
|
||||
[]);
|
||||
@ -218,21 +265,87 @@ export function main() {
|
||||
expect(summaries[0].metadata).toEqual({
|
||||
local: symbolCache.get('/tmp/local.d.ts', 'local'),
|
||||
external: symbolCache.get('/tmp/external.d.ts', 'PROVIDERS'),
|
||||
externalNonSummary: symbolCache.get('/tmp/non_summary.d.ts', 'external')
|
||||
externalNonSummary: symbolCache.get('/tmp/non_summary.d.ts', 'external'),
|
||||
reexportNonExistent: symbolCache.get('/tmp/external.d.ts', 'ReexportNonExistent'),
|
||||
});
|
||||
expect(summaries[1].symbol).toBe(symbolCache.get('/tmp/external.d.ts', 'PROVIDERS'));
|
||||
expect(summaries[1].metadata).toEqual([symbolCache.get(
|
||||
'/tmp/external_svc.d.ts', 'SomeService')]);
|
||||
// SomService is a transitive dep, but should have been serialized as well.
|
||||
expect(summaries[2].symbol).toBe(symbolCache.get('/tmp/external_svc.d.ts', 'SomeService'));
|
||||
expect(summaries[2].type !.type.reference)
|
||||
.toBe(symbolCache.get('/tmp/external_svc.d.ts', 'SomeService'));
|
||||
// there was no summary for non_summary, but it should have
|
||||
// been serialized as well.
|
||||
expect(summaries[2].symbol).toBe(symbolCache.get('/tmp/non_summary.d.ts', 'external'));
|
||||
expect(summaries[2].metadata).toEqual('b');
|
||||
// SomService is a transitive dep, but should have been serialized as well.
|
||||
expect(summaries[3].symbol).toBe(symbolCache.get('/tmp/external_svc.d.ts', 'SomeService'));
|
||||
expect(summaries[3].type !.type.reference)
|
||||
.toBe(symbolCache.get('/tmp/external_svc.d.ts', 'SomeService'));
|
||||
expect(summaries[3].symbol).toBe(symbolCache.get('/tmp/non_summary.d.ts', 'external'));
|
||||
expect(summaries[3].metadata).toEqual('b');
|
||||
});
|
||||
|
||||
it('should resolve reexported values in libraries', () => {
|
||||
init();
|
||||
const externalSerialized = serializeSummaries(
|
||||
'someFile.ts', createMockOutputContext(), summaryResolver, symbolResolver,
|
||||
[
|
||||
{symbol: symbolCache.get('/tmp/external.ts', 'value'), metadata: 'someString'},
|
||||
{
|
||||
symbol: symbolCache.get('/tmp/external.ts', 'reexportValue'),
|
||||
metadata: symbolCache.get('/tmp/external.ts', 'value')
|
||||
},
|
||||
],
|
||||
[]);
|
||||
init({
|
||||
'/tmp/external.ngsummary.json': externalSerialized.json,
|
||||
});
|
||||
const serialized = serializeSummaries(
|
||||
'someFile.ts', createMockOutputContext(), summaryResolver, symbolResolver,
|
||||
[
|
||||
{
|
||||
symbol: symbolCache.get('/tmp/test.ts', 'mainValue'),
|
||||
metadata: symbolCache.get('/tmp/external.d.ts', 'reexportValue'),
|
||||
},
|
||||
],
|
||||
[]);
|
||||
|
||||
const summaries =
|
||||
deserializeSummaries(symbolCache, summaryResolver, 'someFile.d.ts', serialized.json)
|
||||
.summaries;
|
||||
expect(summaries.length).toBe(2);
|
||||
expect(summaries[0].symbol).toBe(symbolCache.get('/tmp/test.d.ts', 'mainValue'));
|
||||
expect(summaries[0].metadata).toBe(symbolCache.get('/tmp/external.d.ts', 'value'));
|
||||
expect(summaries[1].symbol).toBe(symbolCache.get('/tmp/external.d.ts', 'value'));
|
||||
expect(summaries[1].metadata).toBe('someString');
|
||||
});
|
||||
|
||||
it('should not create "importAs" names for reexported types in libraries', () => {
|
||||
init();
|
||||
const externalSerialized = serializeSummaries(
|
||||
'someFile.ts', createMockOutputContext(), summaryResolver, symbolResolver,
|
||||
[
|
||||
{
|
||||
symbol: symbolCache.get('/tmp/external.ts', 'type'),
|
||||
metadata: {__symbolic: 'interface'}
|
||||
},
|
||||
{
|
||||
symbol: symbolCache.get('/tmp/external.ts', 'reexportType'),
|
||||
metadata: symbolCache.get('/tmp/external.ts', 'type')
|
||||
},
|
||||
],
|
||||
[]);
|
||||
init({
|
||||
'/tmp/external.ngsummary.json': externalSerialized.json,
|
||||
});
|
||||
const serialized = serializeSummaries(
|
||||
'someFile.ts', createMockOutputContext(), summaryResolver, symbolResolver, [{
|
||||
symbol: symbolCache.get('/tmp/test.ts', 'mainType'),
|
||||
metadata: symbolCache.get('/tmp/external.d.ts', 'reexportType'),
|
||||
}],
|
||||
[]);
|
||||
const importAs =
|
||||
deserializeSummaries(symbolCache, summaryResolver, 'someFile.d.ts', serialized.json)
|
||||
.importAs;
|
||||
expect(importAs).toEqual([]);
|
||||
});
|
||||
|
||||
it('should create "importAs" names for non source symbols', () => {
|
||||
init();
|
||||
const serialized = serializeSummaries(
|
||||
|
Reference in New Issue
Block a user