fix(ngcc): fix undecorated child migration when exportAs is present (#34014)

The undecorated child migration creates a synthetic decorator, which
contained `"exportAs": ["exportName"]` as obtained from the metadata of
the parent class. This is a problem, as `exportAs` needs to specified
as a comma-separated string instead of an array. This commit fixes the
bug by transforming the array of export names back to a comma-separated
string.

PR Close #34014
This commit is contained in:
JoostK 2019-11-23 19:33:18 +01:00 committed by Andrew Kushnir
parent 95429d55ff
commit ead169a402
2 changed files with 8 additions and 11 deletions

View File

@ -51,7 +51,7 @@ export function createDirectiveDecorator(
metaArgs.push(property('selector', metadata.selector)); metaArgs.push(property('selector', metadata.selector));
} }
if (metadata.exportAs !== null) { if (metadata.exportAs !== null) {
metaArgs.push(property('exportAs', metadata.exportAs)); metaArgs.push(property('exportAs', metadata.exportAs.join(', ')));
} }
args.push(reifySourceFile(ts.createObjectLiteral(metaArgs))); args.push(reifySourceFile(ts.createObjectLiteral(metaArgs)));
} }
@ -77,7 +77,7 @@ export function createComponentDecorator(
metaArgs.push(property('selector', metadata.selector)); metaArgs.push(property('selector', metadata.selector));
} }
if (metadata.exportAs !== null) { if (metadata.exportAs !== null) {
metaArgs.push(property('exportAs', metadata.exportAs)); metaArgs.push(property('exportAs', metadata.exportAs.join(', ')));
} }
return { return {
name: 'Component', name: 'Component',
@ -105,13 +105,8 @@ export function createInjectableDecorator(clazz: ClassDeclaration): Decorator {
}; };
} }
function property(name: string, value: string | string[]): ts.PropertyAssignment { function property(name: string, value: string): ts.PropertyAssignment {
if (typeof value === 'string') { return ts.createPropertyAssignment(name, ts.createStringLiteral(value));
return ts.createPropertyAssignment(name, ts.createStringLiteral(value));
} else {
return ts.createPropertyAssignment(
name, ts.createArrayLiteral(value.map(v => ts.createStringLiteral(v))));
}
} }
const EMPTY_SF = ts.createSourceFile('(empty)', '', ts.ScriptTarget.Latest); const EMPTY_SF = ts.createSourceFile('(empty)', '', ts.ScriptTarget.Latest);

View File

@ -972,6 +972,7 @@ runInEachFileSystem(() => {
@Directive({ @Directive({
selector: '[base]', selector: '[base]',
exportAs: 'base1, base2',
}) })
export class BaseDir {} export class BaseDir {}
@ -994,13 +995,14 @@ runInEachFileSystem(() => {
const jsContents = fs.readFile(_(`/node_modules/test-package/index.js`)); const jsContents = fs.readFile(_(`/node_modules/test-package/index.js`));
expect(jsContents) expect(jsContents)
.toContain( .toContain(
'DerivedDir.ɵdir = ɵngcc0.ɵɵdefineDirective({ type: DerivedDir, selectors: [["", "base", ""]], ' + 'DerivedDir.ɵdir = ɵngcc0.ɵɵdefineDirective({ type: DerivedDir, ' +
'selectors: [["", "base", ""]], exportAs: ["base1", "base2"], ' +
'features: [ɵngcc0.ɵɵInheritDefinitionFeature, ɵngcc0.ɵɵCopyDefinitionFeature] });'); 'features: [ɵngcc0.ɵɵInheritDefinitionFeature, ɵngcc0.ɵɵCopyDefinitionFeature] });');
const dtsContents = fs.readFile(_(`/node_modules/test-package/index.d.ts`)); const dtsContents = fs.readFile(_(`/node_modules/test-package/index.d.ts`));
expect(dtsContents) expect(dtsContents)
.toContain( .toContain(
'static ɵdir: ɵngcc0.ɵɵDirectiveDefWithMeta<DerivedDir, "[base]", never, {}, {}, never>;'); 'static ɵdir: ɵngcc0.ɵɵDirectiveDefWithMeta<DerivedDir, "[base]", ["base1", "base2"], {}, {}, never>;');
}); });
it('should generate a component definition with CopyDefinitionFeature for an undecorated child component', it('should generate a component definition with CopyDefinitionFeature for an undecorated child component',