Skip to content

Commit

Permalink
feat(compiler-cli): enableIvy true value is an alias for ngtsc
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
filipesilva committed Feb 12, 2019
1 parent 1e64f37 commit 51fa0cc
Show file tree
Hide file tree
Showing 7 changed files with 14 additions and 201 deletions.
2 changes: 1 addition & 1 deletion packages/bazel/src/ng_module.bzl
Expand Up @@ -74,7 +74,7 @@ def _enable_ivy_value(ctx):
if strategy == "legacy":
return False
elif strategy == "aot":
return "ngtsc"
return True
else:
fail("unreachable")

Expand Down
5 changes: 2 additions & 3 deletions packages/compiler-cli/src/main.ts
Expand Up @@ -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;
Expand Down Expand Up @@ -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(
Expand Down
4 changes: 4 additions & 0 deletions packages/compiler-cli/src/perform_compile.ts
Expand Up @@ -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};
}

Expand Down
5 changes: 2 additions & 3 deletions packages/compiler-cli/src/transformers/api.ts
Expand Up @@ -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
Expand Down
7 changes: 3 additions & 4 deletions packages/compiler-cli/src/transformers/program.ts
Expand Up @@ -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(
Expand Down Expand Up @@ -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);
Expand Down
188 changes: 0 additions & 188 deletions packages/compiler-cli/test/ngc_spec.ts
Expand Up @@ -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: '<h1><div style="text-align:center"> Hello, {{name}}! </div></h1> '
})
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 {
Expand Down Expand Up @@ -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(`{
Expand Down
4 changes: 2 additions & 2 deletions packages/compiler-cli/test/ngtsc/env.ts
Expand Up @@ -70,7 +70,7 @@ export class NgtscTestEnvironment {
"typeRoots": ["node_modules/@types"]
},
"angularCompilerOptions": {
"enableIvy": "ngtsc"
"enableIvy": true
}
}`);

Expand Down Expand Up @@ -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 = {
Expand Down

0 comments on commit 51fa0cc

Please sign in to comment.