From d56724659f7705fc7676a7375dcb667d7588515a Mon Sep 17 00:00:00 2001 From: Tobias Bosch Date: Wed, 25 Oct 2017 08:13:56 -0700 Subject: [PATCH] =?UTF-8?q?fix(compiler):=20automatically=20set=20`emitDec?= =?UTF-8?q?oratorMetadata`=20when=20`"annotationsAs":=20"static=20fields?= =?UTF-8?q?=E2=80=9D`=20(#19927)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a workaround for https://github.com/angular/tsickle/issues/635. Fixes #19916 PR Close #19927 --- packages/compiler-cli/src/main.ts | 6 +++ packages/compiler-cli/test/ngc_spec.ts | 60 +++++++++++++++++++++----- 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/packages/compiler-cli/src/main.ts b/packages/compiler-cli/src/main.ts index 7dd8ac90aa..593345060a 100644 --- a/packages/compiler-cli/src/main.ts +++ b/packages/compiler-cli/src/main.ts @@ -45,6 +45,12 @@ function createEmitCallback(options: api.CompilerOptions): api.TsEmitCallback|un if (!transformDecorators && !transformTypesToClosure) { return undefined; } + if (transformDecorators) { + // This is needed as a workaround for https://github.com/angular/tsickle/issues/635 + // Otherwise tsickle might emit references to non imported values + // as TypeScript elided the import. + options.emitDecoratorMetadata = true; + } const tsickleHost: tsickle.TsickleHost = { shouldSkipTsickleProcessing: (fileName) => /\.d\.ts$/.test(fileName) || GENERATED_FILES.test(fileName), diff --git a/packages/compiler-cli/test/ngc_spec.ts b/packages/compiler-cli/test/ngc_spec.ts index 7882cb80de..d51b49fdc4 100644 --- a/packages/compiler-cli/test/ngc_spec.ts +++ b/packages/compiler-cli/test/ngc_spec.ts @@ -502,29 +502,69 @@ describe('ngc transformer command-line', () => { it('should add metadata as decorators', () => { writeConfig(`{ "extends": "./tsconfig-base.json", + "compilerOptions": { + "emitDecoratorMetadata": true + }, "angularCompilerOptions": { "annotationsAs": "decorators" }, "files": ["mymodule.ts"] }`); + write('aclass.ts', `export class AClass {}`); write('mymodule.ts', ` - import {NgModule, Component} from '@angular/core'; + import {NgModule} from '@angular/core'; + import {AClass} from './aclass'; - @Component({template: ''}) - export class MyComp { - fn(p: any) {} - } - - @NgModule({declarations: [MyComp]}) - export class MyModule {} - `); + @NgModule({declarations: []}) + export class MyModule { + constructor(importedClass: AClass) {} + } + `); const exitCode = main(['-p', basePath], errorSpy); expect(exitCode).toEqual(0); const mymodulejs = path.resolve(outDir, 'mymodule.js'); const mymoduleSource = fs.readFileSync(mymodulejs, 'utf8'); - expect(mymoduleSource).toContain('MyComp = __decorate(['); + expect(mymoduleSource).toContain('MyModule = __decorate(['); + expect(mymoduleSource).toContain(`import { AClass } from './aclass';`); + expect(mymoduleSource).toContain(`__metadata("design:paramtypes", [AClass])`); + }); + + it('should add metadata as static fields', () => { + // Note: Don't specify emitDecoratorMetadata here on purpose, + // as regression test for https://github.com/angular/angular/issues/19916. + writeConfig(`{ + "extends": "./tsconfig-base.json", + "compilerOptions": { + "emitDecoratorMetadata": false + }, + "angularCompilerOptions": { + "annotationsAs": "static fields" + }, + "files": ["mymodule.ts"] + }`); + write('aclass.ts', `export class AClass {}`); + write('mymodule.ts', ` + import {NgModule} from '@angular/core'; + import {AClass} from './aclass'; + + @NgModule({declarations: []}) + export class MyModule { + constructor(importedClass: AClass) {} + } + `); + + const exitCode = main(['-p', basePath], errorSpy); + expect(exitCode).toEqual(0); + + const mymodulejs = path.resolve(outDir, 'mymodule.js'); + const mymoduleSource = fs.readFileSync(mymodulejs, 'utf8'); + expect(mymoduleSource).not.toContain('__decorate'); + expect(mymoduleSource).toContain('args: [{ declarations: [] },] }'); + expect(mymoduleSource).not.toContain(`__metadata`); + expect(mymoduleSource).toContain(`import { AClass } from './aclass';`); + expect(mymoduleSource).toContain(`{ type: AClass, }`); }); });