fix(ngcc): always add exports for ModuleWithProviders
references (#33875)
In #32902 a bug was supposedly fixed where internal classes as used within `ModuleWithProviders` are publicly exported, even when the typings file already contained the generic type on the `ModuleWithProviders`. This fix turns out to have been incomplete, as the `ModuleWithProviders` analysis is not done when not processing the typings files. The effect of this bug is that formats that are processed after the initial format had been processed would not have exports for internal symbols, resulting in "export '...' was not found in '...'" errors. This commit fixes the bug by always running the `ModuleWithProviders` analyzer. An integration test has been added that would fail prior to this change. Fixes #33701 PR Close #33875
This commit is contained in:
@ -338,7 +338,8 @@ runInEachFileSystem(() => {
|
||||
new MockLogger(), false, program.getTypeChecker(), dtsProgram);
|
||||
referencesRegistry = new NgccReferencesRegistry(host);
|
||||
|
||||
const analyzer = new ModuleWithProvidersAnalyzer(host, referencesRegistry);
|
||||
const processDts = true;
|
||||
const analyzer = new ModuleWithProvidersAnalyzer(host, referencesRegistry, processDts);
|
||||
analyses = analyzer.analyzeProgram(program);
|
||||
});
|
||||
|
||||
@ -427,21 +428,19 @@ runInEachFileSystem(() => {
|
||||
|
||||
describe('tracking references when generic types already present', () => {
|
||||
let _: typeof absoluteFrom;
|
||||
let analyses: ModuleWithProvidersAnalyses;
|
||||
let program: ts.Program;
|
||||
let dtsProgram: BundleProgram;
|
||||
let referencesRegistry: NgccReferencesRegistry;
|
||||
let TEST_DTS_PROGRAM: TestFile[];
|
||||
let TEST_PROGRAM: TestFile[];
|
||||
|
||||
beforeEach(() => {
|
||||
_ = absoluteFrom;
|
||||
|
||||
const TEST_PROGRAM: TestFile[] = [
|
||||
TEST_PROGRAM = [
|
||||
{
|
||||
name: _('/node_modules/test-package/src/entry-point.js'),
|
||||
contents: `
|
||||
export * from './explicit';
|
||||
export * from './module';
|
||||
`
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: _('/node_modules/test-package/src/explicit.js'),
|
||||
@ -469,26 +468,26 @@ runInEachFileSystem(() => {
|
||||
};
|
||||
}
|
||||
}
|
||||
`
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: _('/node_modules/test-package/src/module.js'),
|
||||
contents: `
|
||||
export class ExternalModule {}
|
||||
`
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: _('/node_modules/some-library/index.d.ts'),
|
||||
contents: 'export declare class LibraryModule {}'
|
||||
contents: 'export declare class LibraryModule {}',
|
||||
},
|
||||
];
|
||||
const TEST_DTS_PROGRAM: TestFile[] = [
|
||||
TEST_DTS_PROGRAM = [
|
||||
{
|
||||
name: _('/node_modules/test-package/typings/entry-point.d.ts'),
|
||||
contents: `
|
||||
export * from './explicit';
|
||||
export * from './module';
|
||||
`
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: _('/node_modules/test-package/typings/explicit.d.ts'),
|
||||
@ -502,13 +501,13 @@ runInEachFileSystem(() => {
|
||||
static explicitExternalMethod(): ModuleWithProviders<ExternalModule>;
|
||||
static explicitLibraryMethod(): ModuleWithProviders<LibraryModule>;
|
||||
}
|
||||
`
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: _('/node_modules/test-package/typings/module.d.ts'),
|
||||
contents: `
|
||||
export declare class ExternalModule {}
|
||||
`
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: _('/node_modules/test-package/typings/core.d.ts'),
|
||||
@ -522,29 +521,31 @@ runInEachFileSystem(() => {
|
||||
ngModule: Type<T>
|
||||
providers?: Provider[]
|
||||
}
|
||||
`
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: _('/node_modules/some-library/index.d.ts'),
|
||||
contents: 'export declare class LibraryModule {}'
|
||||
contents: 'export declare class LibraryModule {}',
|
||||
},
|
||||
];
|
||||
loadTestFiles(TEST_PROGRAM);
|
||||
loadTestFiles(TEST_DTS_PROGRAM);
|
||||
const bundle = makeTestEntryPointBundle(
|
||||
'test-package', 'esm2015', false, getRootFiles(TEST_PROGRAM),
|
||||
getRootFiles(TEST_DTS_PROGRAM));
|
||||
program = bundle.src.program;
|
||||
dtsProgram = bundle.dts !;
|
||||
const host =
|
||||
new Esm2015ReflectionHost(new MockLogger(), false, program.getTypeChecker(), dtsProgram);
|
||||
referencesRegistry = new NgccReferencesRegistry(host);
|
||||
|
||||
const analyzer = new ModuleWithProvidersAnalyzer(host, referencesRegistry);
|
||||
analyses = analyzer.analyzeProgram(program);
|
||||
});
|
||||
|
||||
it('should track references even when nothing needs to be updated', () => {
|
||||
const bundle = makeTestEntryPointBundle(
|
||||
'test-package', 'esm2015', false, getRootFiles(TEST_PROGRAM),
|
||||
getRootFiles(TEST_DTS_PROGRAM));
|
||||
const program = bundle.src.program;
|
||||
const dtsProgram = bundle.dts !;
|
||||
const host =
|
||||
new Esm2015ReflectionHost(new MockLogger(), false, program.getTypeChecker(), dtsProgram);
|
||||
const referencesRegistry = new NgccReferencesRegistry(host);
|
||||
|
||||
const processDts = true;
|
||||
const analyzer = new ModuleWithProvidersAnalyzer(host, referencesRegistry, processDts);
|
||||
const analyses = analyzer.analyzeProgram(program);
|
||||
|
||||
const file = getSourceFileOrError(
|
||||
dtsProgram.program, _('/node_modules/test-package/typings/explicit.d.ts'));
|
||||
expect(analyses.has(file)).toBe(false);
|
||||
@ -563,5 +564,34 @@ runInEachFileSystem(() => {
|
||||
expect(declarations.has(externalModuleDeclaration.name !)).toBe(true);
|
||||
expect(declarations.has(libraryModuleDeclaration.name !)).toBe(false);
|
||||
});
|
||||
|
||||
it('should track references even when typings have already been processed', () => {
|
||||
const bundle =
|
||||
makeTestEntryPointBundle('test-package', 'esm2015', false, getRootFiles(TEST_PROGRAM));
|
||||
const program = bundle.src.program;
|
||||
const host =
|
||||
new Esm2015ReflectionHost(new MockLogger(), false, program.getTypeChecker(), null);
|
||||
const referencesRegistry = new NgccReferencesRegistry(host);
|
||||
|
||||
const processDts = false; // Emulate the scenario where typings have already been processed
|
||||
const analyzer = new ModuleWithProvidersAnalyzer(host, referencesRegistry, processDts);
|
||||
const analyses = analyzer.analyzeProgram(program);
|
||||
|
||||
expect(analyses.size).toBe(0);
|
||||
|
||||
const declarations = referencesRegistry.getDeclarationMap();
|
||||
const explicitInternalModuleDeclaration = getDeclaration(
|
||||
program, absoluteFrom('/node_modules/test-package/src/explicit.js'),
|
||||
'ExplicitInternalModule', ts.isClassDeclaration);
|
||||
const externalModuleDeclaration = getDeclaration(
|
||||
program, absoluteFrom('/node_modules/test-package/src/module.js'), 'ExternalModule',
|
||||
ts.isClassDeclaration);
|
||||
const libraryModuleDeclaration = getDeclaration(
|
||||
program, absoluteFrom('/node_modules/some-library/index.d.ts'), 'LibraryModule',
|
||||
ts.isClassDeclaration);
|
||||
expect(declarations.has(explicitInternalModuleDeclaration.name !)).toBe(true);
|
||||
expect(declarations.has(externalModuleDeclaration.name !)).toBe(true);
|
||||
expect(declarations.has(libraryModuleDeclaration.name !)).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Reference in New Issue
Block a user