feat(ivy): ngtsc compiles @Component, @Directive, @NgModule (#24427)

This change supports compilation of components, directives, and modules
within ngtsc. Support is not complete, but is enough to compile and test
//packages/core/test/bundling/todo in full AOT mode. Code size benefits
are not yet achieved as //packages/core itself does not get compiled, and
some decorators (e.g. @Input) are not stripped, leading to unwanted code
being retained by the tree-shaker. This will be improved in future commits.

PR Close #24427
This commit is contained in:
Alex Rickabaugh
2018-05-31 15:50:02 -07:00
committed by Miško Hevery
parent 0f7e4fae20
commit 27bc7dcb43
69 changed files with 1884 additions and 607 deletions

View File

@ -16,6 +16,8 @@ function callableParamDecorator(): FnWithArg<(a: any, b: any, c: any) => void> {
return null !;
}
export const Component = callableClassDecorator();
export const Directive = callableClassDecorator();
export const Injectable = callableClassDecorator();
export const NgModule = callableClassDecorator();

View File

@ -95,7 +95,7 @@ describe('ngtsc behavioral tests', () => {
}`);
});
it('should compile without errors', () => {
it('should compile Injectables without errors', () => {
writeConfig();
write('test.ts', `
import {Injectable} from '@angular/core';
@ -122,4 +122,62 @@ describe('ngtsc behavioral tests', () => {
expect(dtsContents).toContain('static ngInjectableDef: i0.InjectableDef<Dep>;');
expect(dtsContents).toContain('static ngInjectableDef: i0.InjectableDef<Service>;');
});
it('should compile Components without errors', () => {
writeConfig();
write('test.ts', `
import {Component} from '@angular/core';
@Component({
selector: 'test-cmp',
template: 'this is a test',
})
export class TestCmp {}
`);
const exitCode = main(['-p', basePath], errorSpy);
expect(errorSpy).not.toHaveBeenCalled();
expect(exitCode).toBe(0);
const jsContents = getContents('test.js');
expect(jsContents).toContain('TestCmp.ngComponentDef = i0.ɵdefineComponent');
expect(jsContents).not.toContain('__decorate');
const dtsContents = getContents('test.d.ts');
expect(dtsContents).toContain('static ngComponentDef: i0.ComponentDef<TestCmp, \'test-cmp\'>');
});
it('should compile NgModules without errors', () => {
writeConfig();
write('test.ts', `
import {Component, NgModule} from '@angular/core';
@Component({
selector: 'test-cmp',
template: 'this is a test',
})
export class TestCmp {}
@NgModule({
declarations: [TestCmp],
})
export class TestModule {}
`);
const exitCode = main(['-p', basePath], errorSpy);
expect(errorSpy).not.toHaveBeenCalled();
expect(exitCode).toBe(0);
const jsContents = getContents('test.js');
expect(jsContents)
.toContain(
'i0.ɵdefineNgModule({ type: TestModule, bootstrap: [], ' +
'declarations: [TestCmp], imports: [], exports: [] })');
const dtsContents = getContents('test.d.ts');
expect(dtsContents).toContain('static ngComponentDef: i0.ComponentDef<TestCmp, \'test-cmp\'>');
expect(dtsContents)
.toContain('static ngModuleDef: i0.NgModuleDef<TestModule, [TestCmp], [], []>');
expect(dtsContents).not.toContain('__decorate');
});
});