fix(ivy): ngcc should process undecorated base classes (#30821)
Currently undecorated classes are intentionally not processed with ngcc. This is causing unexpected behavior because decorator handlers such as `base_def.ts` are specifically interested in class definitions without top-level decorators, so that the base definition can be generated if there are Angular-specific class members. In order to ensure that undecorated base-classes work as expected with Ivy, we need to run the decorator handlers for all top-level class declarations (not only for those with decorators). This is similar to when `ngtsc` runs decorator handlers when analyzing source-files. Resolves FW-1355. Fixes https://github.com/angular/components/issues/16178 PR Close #30821
This commit is contained in:

committed by
Igor Minar

parent
271d2b51a9
commit
2b4d5c7548
@ -1587,27 +1587,41 @@ describe('CommonJsReflectionHost', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('findDecoratedClasses()', () => {
|
||||
it('should return an array of all decorated classes in the given source file', () => {
|
||||
describe('findClassSymbols()', () => {
|
||||
it('should return an array of all classes in the given source file', () => {
|
||||
const {program, host: compilerHost} = makeTestBundleProgram(DECORATED_FILES);
|
||||
const host = new CommonJsReflectionHost(new MockLogger(), false, program, compilerHost);
|
||||
const primary = program.getSourceFile(DECORATED_FILES[0].name) !;
|
||||
const primaryFile = program.getSourceFile(DECORATED_FILES[0].name) !;
|
||||
const secondaryFile = program.getSourceFile(DECORATED_FILES[1].name) !;
|
||||
|
||||
const primaryDecoratedClasses = host.findDecoratedClasses(primary);
|
||||
expect(primaryDecoratedClasses.length).toEqual(2);
|
||||
const classA = primaryDecoratedClasses.find(c => c.name === 'A') !;
|
||||
expect(classA.decorators.map(decorator => decorator.name)).toEqual(['Directive']);
|
||||
// Note that `B` is not exported from `primary.js`
|
||||
const classB = primaryDecoratedClasses.find(c => c.name === 'B') !;
|
||||
expect(classB.decorators.map(decorator => decorator.name)).toEqual(['Directive']);
|
||||
const classSymbolsPrimary = host.findClassSymbols(primaryFile);
|
||||
expect(classSymbolsPrimary.length).toEqual(2);
|
||||
expect(classSymbolsPrimary.map(c => c.name)).toEqual(['A', 'B']);
|
||||
|
||||
const secondary = program.getSourceFile(DECORATED_FILES[1].name) !;
|
||||
const secondaryDecoratedClasses = host.findDecoratedClasses(secondary);
|
||||
expect(secondaryDecoratedClasses.length).toEqual(1);
|
||||
// Note that `D` is exported from `secondary.js` but not exported from `primary.js`
|
||||
const classD = secondaryDecoratedClasses.find(c => c.name === 'D') !;
|
||||
expect(classD.name).toEqual('D');
|
||||
expect(classD.decorators.map(decorator => decorator.name)).toEqual(['Directive']);
|
||||
const classSymbolsSecondary = host.findClassSymbols(secondaryFile);
|
||||
expect(classSymbolsSecondary.length).toEqual(1);
|
||||
expect(classSymbolsSecondary.map(c => c.name)).toEqual(['D']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getDecoratorsOfSymbol()', () => {
|
||||
it('should return decorators of class symbol', () => {
|
||||
const {program, host: compilerHost} = makeTestBundleProgram(DECORATED_FILES);
|
||||
const host = new CommonJsReflectionHost(new MockLogger(), false, program, compilerHost);
|
||||
const primaryFile = program.getSourceFile(DECORATED_FILES[0].name) !;
|
||||
const secondaryFile = program.getSourceFile(DECORATED_FILES[1].name) !;
|
||||
|
||||
const classSymbolsPrimary = host.findClassSymbols(primaryFile);
|
||||
const classDecoratorsPrimary = classSymbolsPrimary.map(s => host.getDecoratorsOfSymbol(s));
|
||||
expect(classDecoratorsPrimary.length).toEqual(2);
|
||||
expect(classDecoratorsPrimary[0] !.map(d => d.name)).toEqual(['Directive']);
|
||||
expect(classDecoratorsPrimary[1] !.map(d => d.name)).toEqual(['Directive']);
|
||||
|
||||
const classSymbolsSecondary = host.findClassSymbols(secondaryFile);
|
||||
const classDecoratorsSecondary =
|
||||
classSymbolsSecondary.map(s => host.getDecoratorsOfSymbol(s));
|
||||
expect(classDecoratorsSecondary.length).toEqual(1);
|
||||
expect(classDecoratorsSecondary[0] !.map(d => d.name)).toEqual(['Directive']);
|
||||
});
|
||||
});
|
||||
|
||||
|
Reference in New Issue
Block a user