From 51fa0cc5b6c215609c8c84f2334c37fbb130d719 Mon Sep 17 00:00:00 2001 From: Filipe Silva Date: Fri, 8 Feb 2019 11:37:21 +0000 Subject: [PATCH] feat(compiler-cli): enableIvy true value is an alias for ngtsc Currently setting `enableIvy` to true runs a hybrid mode of `ngc` and `ngtsc`. This is counterintuitive given the name of the flag itself. This PR makes the `true` value an alias for `ngtsc`. Effectively this removes the hybrid mode as well since there's no other way to enable it. --- packages/bazel/src/ng_module.bzl | 2 +- packages/compiler-cli/src/main.ts | 5 +- packages/compiler-cli/src/perform_compile.ts | 4 + packages/compiler-cli/src/transformers/api.ts | 5 +- .../compiler-cli/src/transformers/program.ts | 7 +- packages/compiler-cli/test/ngc_spec.ts | 188 ------------------ packages/compiler-cli/test/ngtsc/env.ts | 4 +- 7 files changed, 14 insertions(+), 201 deletions(-) diff --git a/packages/bazel/src/ng_module.bzl b/packages/bazel/src/ng_module.bzl index 8cb4639665da9..9183ea07c6a09 100644 --- a/packages/bazel/src/ng_module.bzl +++ b/packages/bazel/src/ng_module.bzl @@ -74,7 +74,7 @@ def _enable_ivy_value(ctx): if strategy == "legacy": return False elif strategy == "aot": - return "ngtsc" + return True else: fail("unreachable") diff --git a/packages/compiler-cli/src/main.ts b/packages/compiler-cli/src/main.ts index 8446b19e0fb52..6081da428526c 100644 --- a/packages/compiler-cli/src/main.ts +++ b/packages/compiler-cli/src/main.ts @@ -54,8 +54,7 @@ export function mainDiagnosticsForTest( } function createEmitCallback(options: api.CompilerOptions): api.TsEmitCallback|undefined { - const transformDecorators = options.enableIvy !== 'ngtsc' && options.enableIvy !== 'tsc' && - options.annotationsAs !== 'decorators'; + const transformDecorators = options.enableIvy === false && options.annotationsAs !== 'decorators'; const transformTypesToClosure = options.annotateForClosureCompiler; if (!transformDecorators && !transformTypesToClosure) { return undefined; @@ -192,7 +191,7 @@ function reportErrorsAndExit( const errorsAndWarnings = filterErrorsAndWarnings(allDiagnostics); if (errorsAndWarnings.length) { const formatHost = getFormatDiagnosticsHost(options); - if (options && (options.enableIvy === true || options.enableIvy === 'ngtsc')) { + if (options && options.enableIvy === true) { const ngDiagnostics = errorsAndWarnings.filter(api.isNgDiagnostic); const tsDiagnostics = errorsAndWarnings.filter(api.isTsDiagnostic); consoleError(replaceTsWithNgInErrors( diff --git a/packages/compiler-cli/src/perform_compile.ts b/packages/compiler-cli/src/perform_compile.ts index e62950cdc47b4..a7371c4039545 100644 --- a/packages/compiler-cli/src/perform_compile.ts +++ b/packages/compiler-cli/src/perform_compile.ts @@ -120,6 +120,10 @@ export function calcProjectFileAndBasePath(project: string): export function createNgCompilerOptions( basePath: string, config: any, tsOptions: ts.CompilerOptions): api.CompilerOptions { + // enableIvy `ngtsc` is an alias for `true`. + if (config.angularCompilerOptions && config.angularCompilerOptions.enableIvy === 'ngtsc') { + config.angularCompilerOptions.enableIvy = true; + } return {...tsOptions, ...config.angularCompilerOptions, genDir: basePath, basePath}; } diff --git a/packages/compiler-cli/src/transformers/api.ts b/packages/compiler-cli/src/transformers/api.ts index b0fa3e193e30c..392ac68f91df2 100644 --- a/packages/compiler-cli/src/transformers/api.ts +++ b/packages/compiler-cli/src/transformers/api.ts @@ -188,9 +188,8 @@ export interface CompilerOptions extends ts.CompilerOptions { * Acceptable values are as follows: * * `false` - run ngc normally - * `true` - run ngc with its usual global analysis, but compile decorators to Ivy fields instead - * of running the View Engine compilers - * `ngtsc` - run the ngtsc compiler instead of the normal ngc compiler + * `true` - run the ngtsc compiler instead of the normal ngc compiler + * `ngtsc` - alias for `true` * `tsc` - behave like plain tsc as much as possible (used for testing JIT code) * * @publicApi diff --git a/packages/compiler-cli/src/transformers/program.ts b/packages/compiler-cli/src/transformers/program.ts index 85574b48a3301..a01e5d27e27cb 100644 --- a/packages/compiler-cli/src/transformers/program.ts +++ b/packages/compiler-cli/src/transformers/program.ts @@ -263,11 +263,10 @@ class AngularCompilerProgram implements Program { emitCallback?: TsEmitCallback, mergeEmitResultsCallback?: TsMergeEmitResultsCallback, } = {}): ts.EmitResult { - if (this.options.enableIvy === 'ngtsc' || this.options.enableIvy === 'tsc') { + if (this.options.enableIvy) { throw new Error('Cannot run legacy compiler in ngtsc mode'); } - return this.options.enableIvy === true ? this._emitRender3(parameters) : - this._emitRender2(parameters); + return this._emitRender2(parameters); } private _emitRender3( @@ -899,7 +898,7 @@ export function createProgram({rootNames, options, host, oldProgram}: { options: CompilerOptions, host: CompilerHost, oldProgram?: Program }): Program { - if (options.enableIvy === 'ngtsc') { + if (options.enableIvy === true) { return new NgtscProgram(rootNames, options, host, oldProgram); } else if (options.enableIvy === 'tsc') { return new TscPassThroughProgram(rootNames, options, host, oldProgram); diff --git a/packages/compiler-cli/test/ngc_spec.ts b/packages/compiler-cli/test/ngc_spec.ts index 89d388cf0fb1e..c8ea1b3331f8d 100644 --- a/packages/compiler-cli/test/ngc_spec.ts +++ b/packages/compiler-cli/test/ngc_spec.ts @@ -1850,108 +1850,6 @@ describe('ngc transformer command-line', () => { }); }); - describe('ivy', () => { - function emittedFile(name: string): string { - const outputName = path.resolve(outDir, name); - expect(fs.existsSync(outputName)).toBe(true); - return fs.readFileSync(outputName, {encoding: 'UTF-8'}); - } - - it('should emit the hello world example', () => { - write('tsconfig.json', `{ - "extends": "./tsconfig-base.json", - "files": ["hello-world.ts"], - "angularCompilerOptions": { - "enableIvy": true - } - }`); - - write('hello-world.ts', ` - import {Component, NgModule} from '@angular/core'; - - @Component({ - selector: 'hello-world', - template: 'Hello, world!' - }) - export class HelloWorldComponent { - - } - - @NgModule({ - declarations: [HelloWorldComponent] - }) - export class HelloWorldModule {} - `); - const exitCode = main(['-p', path.join(basePath, 'tsconfig.json')]); - expect(exitCode).toBe(0, 'Compile failed'); - expect(emittedFile('hello-world.js')).toContain('ngComponentDef'); - expect(emittedFile('hello-world.js')).toContain('HelloWorldComponent_Factory'); - }); - - it('should emit an injection of a string token', () => { - write('tsconfig.json', `{ - "extends": "./tsconfig-base.json", - "files": ["hello-world.ts"], - "angularCompilerOptions": { - "enableIvy": true - } - }`); - - write('hello-world.ts', ` - import {Component, Inject, NgModule} from '@angular/core'; - - @Component({ - selector: 'hello-world', - template: 'Hello, world!' - }) - export class HelloWorldComponent { - constructor (@Inject('test') private test: string) {} - } - - @NgModule({ - declarations: [HelloWorldComponent], - providers: [ - {provide: 'test', useValue: 'test'} - ] - }) - export class HelloWorldModule {} - `); - const errors: string[] = []; - const exitCode = main(['-p', path.join(basePath, 'tsconfig.json')], msg => errors.push(msg)); - expect(exitCode).toBe(0, `Compile failed:\n${errors.join('\n ')}`); - expect(emittedFile('hello-world.js')).toContain('ngComponentDef'); - }); - - it('should emit an example that uses the E() instruction', () => { - write('tsconfig.json', `{ - "extends": "./tsconfig-base.json", - "files": ["hello-world.ts"], - "angularCompilerOptions": { - "enableIvy": true - } - }`); - - write('hello-world.ts', ` - import {Component, NgModule} from '@angular/core'; - - @Component({ - selector: 'hello-world', - template: '

Hello, {{name}}!

' - }) - export class HelloWorldComponent { - name = 'World'; - } - - @NgModule({declarations: [HelloWorldComponent]}) - export class HelloWorldModule {} - `); - const errors: string[] = []; - const exitCode = main(['-p', path.join(basePath, 'tsconfig.json')], msg => errors.push(msg)); - expect(exitCode).toBe(0, `Compile failed:\n${errors.join('\n ')}`); - expect(emittedFile('hello-world.js')).toContain('ngComponentDef'); - }); - }); - describe('tree shakeable services', () => { function compileService(source: string): string { @@ -2170,92 +2068,6 @@ describe('ngc transformer command-line', () => { }); }); - describe('ngInjectorDef', () => { - it('is applied with lowered metadata', () => { - writeConfig(`{ - "extends": "./tsconfig-base.json", - "files": ["module.ts"], - "angularCompilerOptions": { - "enableIvy": true, - "skipTemplateCodegen": true - } - }`); - write('module.ts', ` - import {Injectable, NgModule} from '@angular/core'; - - @Injectable() - export class ServiceA {} - - @Injectable() - export class ServiceB {} - - @NgModule() - export class Exported {} - - @NgModule({ - providers: [ServiceA] - }) - export class Imported { - static forRoot() { - console.log('not statically analyzable'); - return { - ngModule: Imported, - providers: [] as any, - }; - } - } - - @NgModule({ - providers: [ServiceA, ServiceB], - imports: [Imported.forRoot()], - exports: [Exported], - }) - export class Module {} - `); - - const exitCode = main(['-p', path.join(basePath, 'tsconfig.json')], errorSpy); - expect(exitCode).toEqual(0); - - const modulePath = path.resolve(outDir, 'module.js'); - const moduleSource = fs.readFileSync(modulePath, 'utf8'); - expect(moduleSource) - .toContain('var ɵ1 = [ServiceA, ServiceB], ɵ2 = [Imported.forRoot()], ɵ3 = [Exported];'); - expect(moduleSource) - .toContain( - 'Imported.ngInjectorDef = i0.defineInjector({ factory: function Imported_Factory() { return new Imported(); }, providers: ɵ0, imports: [] });'); - expect(moduleSource) - .toContain( - 'Module.ngInjectorDef = i0.defineInjector({ factory: function Module_Factory() { return new Module(); }, providers: ɵ1, imports: [ɵ2, ɵ3] });'); - }); - - it('rewrites Injector to INJECTOR in Ivy factory functions ', () => { - writeConfig(`{ - "extends": "./tsconfig-base.json", - "files": ["service.ts"], - "angularCompilerOptions": { - "enableIvy": true - } - }`); - - write('service.ts', ` - import {Injectable, Injector} from '@angular/core'; - - @Injectable() - export class Service { - constructor(private injector: Injector) {} - } - `); - - const exitCode = main(['-p', path.join(basePath, 'tsconfig.json')], errorSpy); - expect(exitCode).toEqual(0); - - const modulePath = path.resolve(outDir, 'service.js'); - const moduleSource = fs.readFileSync(modulePath, 'utf8'); - expect(moduleSource).not.toMatch(/inject\(i0\.Injector/); - expect(moduleSource).toMatch(/inject\(i0\.INJECTOR/); - }); - }); - it('libraries should not break strictMetadataEmit', () => { // first only generate .d.ts / .js / .metadata.json files writeConfig(`{ diff --git a/packages/compiler-cli/test/ngtsc/env.ts b/packages/compiler-cli/test/ngtsc/env.ts index ae4bdbcf601b3..bb95a3cbb69c9 100644 --- a/packages/compiler-cli/test/ngtsc/env.ts +++ b/packages/compiler-cli/test/ngtsc/env.ts @@ -70,7 +70,7 @@ export class NgtscTestEnvironment { "typeRoots": ["node_modules/@types"] }, "angularCompilerOptions": { - "enableIvy": "ngtsc" + "enableIvy": true } }`); @@ -100,7 +100,7 @@ export class NgtscTestEnvironment { tsconfig(extraOpts: {[key: string]: string | boolean} = {}, extraRootDirs?: string[]): void { const tsconfig: {[key: string]: any} = { extends: './tsconfig-base.json', - angularCompilerOptions: {...extraOpts, enableIvy: 'ngtsc'}, + angularCompilerOptions: {...extraOpts, enableIvy: true}, }; if (extraRootDirs !== undefined) { tsconfig.compilerOptions = {