refactor(ivy): remove ngBaseDef (#33264)

Removes `ngBaseDef` from the compiler and any runtime code that was still referring to it. In the cases where we'd previously generate a base def we now generate a definition for an abstract directive.

PR Close #33264
This commit is contained in:
crisbeto
2019-10-25 19:45:08 +02:00
committed by Andrew Kushnir
parent 3505692f75
commit 14c4b1b205
29 changed files with 310 additions and 660 deletions

View File

@ -2973,7 +2973,7 @@ describe('compiler compliance', () => {
`
};
it('should add ngBaseDef if one or more @Input is present', () => {
it('should add an abstract directive if one or more @Input is present', () => {
const files = {
app: {
'spec.ts': `
@ -3002,7 +3002,9 @@ describe('compiler compliance', () => {
};
const expectedOutput = `
// ...
BaseClass.ngBaseDef = i0.ɵɵdefineBase({
BaseClass.ɵdir = $r3$.ɵɵdefineDirective({
type: BaseClass,
selectors: [],
inputs: {
input1: "input1",
input2: ["alias2", "input2"]
@ -3014,7 +3016,7 @@ describe('compiler compliance', () => {
expectEmit(result.source, expectedOutput, 'Invalid base definition');
});
it('should add ngBaseDef if one or more @Output is present', () => {
it('should add an abstract directive if one or more @Output is present', () => {
const files = {
app: {
'spec.ts': `
@ -3048,7 +3050,9 @@ describe('compiler compliance', () => {
};
const expectedOutput = `
// ...
BaseClass.ngBaseDef = i0.ɵɵdefineBase({
BaseClass.ɵdir = $r3$.ɵɵdefineDirective({
type: BaseClass,
selectors: [],
outputs: {
output1: "output1",
output2: "output2"
@ -3060,10 +3064,11 @@ describe('compiler compliance', () => {
expectEmit(result.source, expectedOutput, 'Invalid base definition');
});
it('should add ngBaseDef if a mixture of @Input and @Output props are present', () => {
const files = {
app: {
'spec.ts': `
it('should add an abstract directive if a mixture of @Input and @Output props are present',
() => {
const files = {
app: {
'spec.ts': `
import {Component, NgModule, Input, Output, EventEmitter} from '@angular/core';
export class BaseClass {
@Output()
@ -3096,11 +3101,13 @@ describe('compiler compliance', () => {
})
export class MyModule {}
`
}
};
const expectedOutput = `
}
};
const expectedOutput = `
// ...
BaseClass.ngBaseDef = i0.ɵɵdefineBase({
BaseClass.ɵdir = $r3$.ɵɵdefineDirective({
type: BaseClass,
selectors: [],
inputs: {
input1: "input1",
input2: ["whatever", "input2"]
@ -3112,11 +3119,11 @@ describe('compiler compliance', () => {
});
// ...
`;
const result = compile(files, angularFiles);
expectEmit(result.source, expectedOutput, 'Invalid base definition');
});
const result = compile(files, angularFiles);
expectEmit(result.source, expectedOutput, 'Invalid base definition');
});
it('should add ngBaseDef if a ViewChild query is present', () => {
it('should add an abstract directive if a ViewChild query is present', () => {
const files = {
app: {
'spec.ts': `
@ -3142,8 +3149,10 @@ describe('compiler compliance', () => {
const expectedOutput = `
const $e0_attrs$ = ["something"];
// ...
BaseClass.ngBaseDef = i0.ɵɵdefineBase({
viewQuery: function (rf, ctx) {
BaseClass.ɵdir = $r3$.ɵɵdefineDirective({
type: BaseClass,
selectors: [],
viewQuery: function BaseClass_Query(rf, ctx) {
if (rf & 1) {
$r3$.ɵɵviewQuery($e0_attrs$, true);
}
@ -3159,7 +3168,7 @@ describe('compiler compliance', () => {
expectEmit(result.source, expectedOutput, 'Invalid base definition');
});
it('should add ngBaseDef if a ViewChildren query is present', () => {
it('should add an abstract directive if a ViewChildren query is present', () => {
const files = {
app: {
...directive,
@ -3187,8 +3196,10 @@ describe('compiler compliance', () => {
};
const expectedOutput = `
// ...
BaseClass.ngBaseDef = i0.ɵɵdefineBase({
viewQuery: function (rf, ctx) {
BaseClass.ɵdir = $r3$.ɵɵdefineDirective({
type: BaseClass,
selectors: [],
viewQuery: function BaseClass_Query(rf, ctx) {
if (rf & 1) {
$r3$.ɵɵviewQuery(SomeDirective, true);
}
@ -3204,7 +3215,7 @@ describe('compiler compliance', () => {
expectEmit(result.source, expectedOutput, 'Invalid base definition');
});
it('should add ngBaseDef if a ContentChild query is present', () => {
it('should add an abstract directive if a ContentChild query is present', () => {
const files = {
app: {
'spec.ts': `
@ -3230,8 +3241,10 @@ describe('compiler compliance', () => {
const expectedOutput = `
const $e0_attrs$ = ["something"];
// ...
BaseClass.ngBaseDef = i0.ɵɵdefineBase({
contentQueries: function (rf, ctx, dirIndex) {
BaseClass.ɵdir = $r3$.ɵɵdefineDirective({
type: BaseClass,
selectors: [],
contentQueries: function BaseClass_ContentQueries(rf, ctx, dirIndex) {
if (rf & 1) {
$r3$.ɵɵcontentQuery(dirIndex, $e0_attrs$, true);
}
@ -3247,7 +3260,7 @@ describe('compiler compliance', () => {
expectEmit(result.source, expectedOutput, 'Invalid base definition');
});
it('should add ngBaseDef if a ContentChildren query is present', () => {
it('should add an abstract directive if a ContentChildren query is present', () => {
const files = {
app: {
...directive,
@ -3275,8 +3288,10 @@ describe('compiler compliance', () => {
};
const expectedOutput = `
// ...
BaseClass.ngBaseDef = i0.ɵɵdefineBase({
contentQueries: function (rf, ctx, dirIndex) {
BaseClass.ɵdir = $r3$.ɵɵdefineDirective({
type: BaseClass,
selectors: [],
contentQueries: function BaseClass_ContentQueries(rf, ctx, dirIndex) {
if (rf & 1) {
$r3$.ɵɵcontentQuery(dirIndex, SomeDirective, false);
}
@ -3292,7 +3307,7 @@ describe('compiler compliance', () => {
expectEmit(result.source, expectedOutput, 'Invalid base definition');
});
it('should add ngBaseDef if a host binding is present', () => {
it('should add an abstract directive if a host binding is present', () => {
const files = {
app: {
'spec.ts': `
@ -3318,8 +3333,10 @@ describe('compiler compliance', () => {
};
const expectedOutput = `
// ...
BaseClass.ngBaseDef = $r3$.ɵɵdefineBase({
hostBindings: function (rf, ctx, elIndex) {
BaseClass.ɵdir = $r3$.ɵɵdefineDirective({
type: BaseClass,
selectors: [],
hostBindings: function BaseClass_HostBindings(rf, ctx, elIndex) {
if (rf & 1) {
$r3$.ɵɵallocHostVars(1);
}
@ -3334,7 +3351,7 @@ describe('compiler compliance', () => {
expectEmit(result.source, expectedOutput, 'Invalid base definition');
});
it('should add ngBaseDef if a host listener is present', () => {
it('should add an abstract directive if a host listener is present', () => {
const files = {
app: {
'spec.ts': `
@ -3360,10 +3377,12 @@ describe('compiler compliance', () => {
};
const expectedOutput = `
// ...
BaseClass.ngBaseDef = $r3$.ɵɵdefineBase({
hostBindings: function (rf, ctx, elIndex) {
BaseClass.ɵdir = $r3$.ɵɵdefineDirective({
type: BaseClass,
selectors: [],
hostBindings: function BaseClass_HostBindings(rf, ctx, elIndex) {
if (rf & 1) {
$r3$.ɵɵlistener("mousedown", function ($event) {
$r3$.ɵɵlistener("mousedown", function BaseClass_mousedown_HostBindingHandler($event) {
return ctx.handleMousedown($event);
});
}
@ -3375,7 +3394,79 @@ describe('compiler compliance', () => {
expectEmit(result.source, expectedOutput, 'Invalid base definition');
});
it('should NOT add ngBaseDef if @Component is present', () => {
it('should add an abstract directive when using any lifecycle hook', () => {
const files = {
app: {
'spec.ts': `
import {Component, NgModule, Input} from '@angular/core';
export class BaseClass {
ngAfterContentChecked() {}
}
@Component({
selector: 'my-component',
template: \`<div>{{input1}} {{input2}}</div>\`
})
export class MyComponent extends BaseClass {
}
@NgModule({
declarations: [MyComponent]
})
export class MyModule {}
`
}
};
const expectedOutput = `
// ...
BaseClass.ɵdir = $r3$.ɵɵdefineDirective({
type: BaseClass,
selectors: []
});
// ...
`;
const result = compile(files, angularFiles);
expectEmit(result.source, expectedOutput, 'Invalid base definition');
});
it('should add an abstract directive when using ngOnChanges', () => {
const files = {
app: {
'spec.ts': `
import {Component, NgModule, Input} from '@angular/core';
export class BaseClass {
ngOnChanges() {}
}
@Component({
selector: 'my-component',
template: \`<div>{{input1}} {{input2}}</div>\`
})
export class MyComponent extends BaseClass {
}
@NgModule({
declarations: [MyComponent]
})
export class MyModule {}
`
}
};
const expectedOutput = `
// ...
BaseClass.ɵdir = $r3$.ɵɵdefineDirective({
type: BaseClass,
selectors: [],
features: [$r3$.ɵɵNgOnChangesFeature()]
});
// ...
`;
const result = compile(files, angularFiles);
expectEmit(result.source, expectedOutput, 'Invalid base definition');
});
it('should NOT add an abstract directive if @Component is present', () => {
const files = {
app: {
'spec.ts': `
@ -3411,10 +3502,10 @@ describe('compiler compliance', () => {
}
};
const result = compile(files, angularFiles);
expect(result.source).not.toContain('ngBaseDef');
expect(result.source).not.toContain('ɵdir');
});
it('should NOT add ngBaseDef if @Directive is present', () => {
it('should NOT add an abstract directive if @Directive is present', () => {
const files = {
app: {
'spec.ts': `
@ -3449,7 +3540,7 @@ describe('compiler compliance', () => {
}
};
const result = compile(files, angularFiles);
expect(result.source).not.toContain('ngBaseDef');
expect(result.source.match(/ɵdir/g) !.length).toBe(1);
});
});
});

View File

@ -16,7 +16,7 @@ describe('compiler compliance: listen()', () => {
compileAnimations: false,
});
it('should create declare inputs/outputs', () => {
it('should declare inputs/outputs', () => {
const files = {
app: {
'spec.ts': `

View File

@ -416,7 +416,7 @@ runInEachFileSystem(os => {
env.driveMain();
const jsContents = env.getContents('test.js');
expect(jsContents).toContain('TestBase.ngBaseDef = i0.ɵɵdefineBase');
expect(jsContents).toContain('TestBase.ɵdir = i0.ɵɵdefineDirective');
expect(jsContents).toContain('TestComponent.ɵcmp = i0.ɵɵdefineComponent');
expect(jsContents).toContain('TestDirective.ɵdir = i0.ɵɵdefineDirective');
expect(jsContents).toContain('TestPipe.ɵpipe = i0.ɵɵdefinePipe');
@ -503,7 +503,7 @@ runInEachFileSystem(os => {
expect(jsContents).toContain('background-color: blue');
});
it('should include generic type for ngBaseDef declarations', () => {
it('should include generic type for undecorated class declarations', () => {
env.write('test.ts', `
import {Component, Input, NgModule} from '@angular/core';
@ -515,10 +515,14 @@ runInEachFileSystem(os => {
env.driveMain();
const jsContents = env.getContents('test.js');
expect(jsContents).toContain('i0.ɵɵdefineBase({ inputs: { input: "input" } });');
expect(jsContents)
.toContain(
'i0.ɵɵdefineDirective({ type: TestBase, selectors: [], inputs: { input: "input" } });');
const dtsContents = env.getContents('test.d.ts');
expect(dtsContents).toContain('static ngBaseDef: i0.ɵɵBaseDef<TestBase>');
expect(dtsContents)
.toContain(
`static ɵdir: i0.ɵɵDirectiveDefWithMeta<TestBase, never, never, { 'input': "input" }, {}, never>;`);
});
it('should compile NgModules without errors', () => {
@ -1104,7 +1108,7 @@ runInEachFileSystem(os => {
}));
env.write('index.ts', `
import {Directive} from '@angular/core';
@Directive()
export class BaseClass {}
`);
@ -1115,10 +1119,10 @@ runInEachFileSystem(os => {
env.write('index.ts', `
import {NgModule, Directive} from '@angular/core';
import {BaseClass} from 'lib1_built';
@Directive({selector: 'my-dir'})
export class MyDirective extends BaseClass {}
@NgModule({declarations: [MyDirective]})
export class AppModule {}
`);
@ -2615,7 +2619,7 @@ runInEachFileSystem(os => {
env.write('test.ts', `/** I am a top-level comment. */
import {NgModule} from '@angular/core';
@NgModule({})
export class TestModule {}
`);
@ -2634,7 +2638,7 @@ runInEachFileSystem(os => {
env.write('my-module.ts', `
import {NgModule} from '@angular/core';
@NgModule({})
export class MyModule {}
`);
@ -2647,7 +2651,7 @@ runInEachFileSystem(os => {
env.write('test.ts', `
import {NgModule} from '@angular/core';
@NgModule({})
export class TestModule {}
`);
@ -2673,9 +2677,9 @@ runInEachFileSystem(os => {
it('should generate a summary stub for decorated classes in the input file only', () => {
env.write('test.ts', `
import {Injectable, NgModule} from '@angular/core';
export class NotAModule {}
@NgModule({})
export class TestModule {}
`);
@ -2689,10 +2693,10 @@ runInEachFileSystem(os => {
it('should generate a summary stub for classes exported via exports', () => {
env.write('test.ts', `
import {Injectable, NgModule} from '@angular/core';
@NgModule({})
class NotDirectlyExported {}
export {NotDirectlyExported};
`);
@ -3597,7 +3601,7 @@ runInEachFileSystem(os => {
it('should not re-export a directive that\'s not exported from the NgModule', () => {
env.write('dir.ts', `
import {Directive} from '@angular/core';
@Directive({
selector: 'dir',
})
@ -3606,7 +3610,7 @@ runInEachFileSystem(os => {
env.write('module.ts', `
import {NgModule} from '@angular/core';
import {Dir} from './dir';
@NgModule({
declarations: [Dir],
exports: [],
@ -3655,11 +3659,11 @@ runInEachFileSystem(os => {
it('should not re-export a directive from an exported, external NgModule', () => {
env.write(`node_modules/external/index.d.ts`, `
import {ɵɵDirectiveDefWithMeta, ɵɵNgModuleDefWithMeta} from '@angular/core';
export declare class ExternalDir {
static ɵdir: ɵɵDirectiveDefWithMeta<ExternalDir, '[test]', never, never, never, never>;
}
export declare class ExternalModule {
static ɵmod: ɵɵNgModuleDefWithMeta<ExternalModule, [typeof ExternalDir], never, [typeof ExternalDir]>;
}
@ -3719,7 +3723,7 @@ runInEachFileSystem(os => {
() => {
env.write('dir.ts', `
import {Directive} from '@angular/core';
@Directive({
selector: 'dir',
})
@ -3727,7 +3731,7 @@ runInEachFileSystem(os => {
`);
env.write('dir2.ts', `
import {Directive} from '@angular/core';
@Directive({
selector: 'dir',
})
@ -3737,7 +3741,7 @@ runInEachFileSystem(os => {
import {NgModule} from '@angular/core';
import {Dir} from './dir';
import {Dir as Dir2} from './dir2';
@NgModule({
declarations: [Dir, Dir2],
exports: [Dir, Dir2],
@ -3755,7 +3759,7 @@ runInEachFileSystem(os => {
it('should choose a re-exported symbol if one is present', () => {
env.write(`node_modules/external/dir.d.ts`, `
import {ɵɵDirectiveDefWithMeta} from '@angular/core';
export declare class ExternalDir {
static ɵdir: ɵɵDirectiveDefWithMeta<ExternalDir, '[test]', never, never, never, never>;
}
@ -3763,23 +3767,23 @@ runInEachFileSystem(os => {
env.write('node_modules/external/module.d.ts', `
import {ɵɵNgModuleDefWithMeta} from '@angular/core';
import {ExternalDir} from './dir';
export declare class ExternalModule {
static ɵmod: ɵɵNgModuleDefWithMeta<ExternalModule, [typeof ExternalDir], never, [typeof ExternalDir]>;
}
export {ExternalDir as ɵngExportɵExternalModuleɵExternalDir};
`);
env.write('test.ts', `
import {Component, Directive, NgModule} from '@angular/core';
import {ExternalModule} from 'external/module';
@Component({
selector: 'test-cmp',
template: '<div test></div>',
})
class Cmp {}
@NgModule({
declarations: [Cmp],
imports: [ExternalModule],