fix(ivy): deduplicate directives in component scopes (#27462)
A previous fix to ngtsc opened the door for duplicate directives in the 'directives' array of a component. This would happen if the directive was declared in a module which was imported more than once within the component's module. This commit adds deduplication when the component's scope is materialized, so declarations which arrive via more than one module import are coalesced. PR Close #27462
This commit is contained in:

committed by
Igor Minar

parent
b82f62a11d
commit
dfdaaf6a0d
@ -60,4 +60,7 @@ export function forwardRef<T>(fn: () => T): T {
|
||||
return fn();
|
||||
}
|
||||
|
||||
export interface SimpleChanges { [propName: string]: any; }
|
||||
export interface SimpleChanges { [propName: string]: any; }
|
||||
|
||||
export type ɵNgModuleDefWithMeta<ModuleT, DeclarationsT, ImportsT, ExportsT> = any;
|
||||
export type ɵDirectiveDefWithMeta<DirT, SelectorT, ExportAsT, InputsT, OutputsT, QueriesT> = any;
|
||||
|
@ -1078,4 +1078,40 @@ describe('ngtsc behavioral tests', () => {
|
||||
|
||||
// Success is enough to indicate that this passes.
|
||||
});
|
||||
|
||||
it('should not emit multiple references to the same directive', () => {
|
||||
env.tsconfig();
|
||||
env.write('node_modules/external/index.d.ts', `
|
||||
import {ɵDirectiveDefWithMeta, ɵNgModuleDefWithMeta} from '@angular/core';
|
||||
|
||||
export declare class ExternalDir {
|
||||
static ngDirectiveDef: ɵDirectiveDefWithMeta<ExternalDir, '[test]', never, never, never, never>;
|
||||
}
|
||||
|
||||
export declare class ExternalModule {
|
||||
static ngModuleDef: ɵNgModuleDefWithMeta<ExternalModule, [typeof ExternalDir], never, [typeof ExternalDir]>;
|
||||
}
|
||||
`);
|
||||
env.write('test.ts', `
|
||||
import {Component, Directive, NgModule} from '@angular/core';
|
||||
import {ExternalModule} from 'external';
|
||||
|
||||
@Component({
|
||||
template: '<div test></div>',
|
||||
})
|
||||
class Cmp {}
|
||||
|
||||
@NgModule({
|
||||
declarations: [Cmp],
|
||||
// Multiple imports of the same module used to result in duplicate directive references
|
||||
// in the output.
|
||||
imports: [ExternalModule, ExternalModule],
|
||||
})
|
||||
class Module {}
|
||||
`);
|
||||
|
||||
env.driveMain();
|
||||
const jsContents = env.getContents('test.js');
|
||||
expect(jsContents).toMatch(/directives: \[i1\.ExternalDir\]/);
|
||||
});
|
||||
});
|
||||
|
Reference in New Issue
Block a user