feat(ivy): generate ngInjectorDef for @NgModule in AOT mode (#24632)

This change generates ngInjectorDef as well as ngModuleDef for @NgModule
annotated types, reflecting the dual nature of @NgModules as both compilation
scopes and as DI configuration containers.

This required implementing ngInjectorDef compilation in @angular/compiler as
well as allowing for multiple generated definitions for a single decorator in
the core of ngtsc.

PR Close #24632
This commit is contained in:
Alex Rickabaugh
2018-06-18 16:28:02 -07:00
committed by Jason Aden
parent 166d90d2a9
commit ae9418c7de
13 changed files with 174 additions and 44 deletions

View File

@ -180,4 +180,46 @@ describe('ngtsc behavioral tests', () => {
.toContain('static ngModuleDef: i0.NgModuleDef<TestModule, [TestCmp], [], []>');
expect(dtsContents).not.toContain('__decorate');
});
it('should compile NgModules with services without errors', () => {
writeConfig();
write('test.ts', `
import {Component, NgModule} from '@angular/core';
export class Token {}
@NgModule({})
export class OtherModule {}
@Component({
selector: 'test-cmp',
template: 'this is a test',
})
export class TestCmp {}
@NgModule({
declarations: [TestCmp],
providers: [{provide: Token, useValue: 'test'}],
imports: [OtherModule],
})
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,');
expect(jsContents)
.toContain(
`TestModule.ngInjectorDef = i0.defineInjector({ factory: ` +
`function TestModule_Factory() { return new TestModule(); }, providers: [{ provide: ` +
`Token, useValue: 'test' }], imports: [OtherModule] });`);
const dtsContents = getContents('test.d.ts');
expect(dtsContents)
.toContain('static ngModuleDef: i0.NgModuleDef<TestModule, [TestCmp], [OtherModule], []>');
expect(dtsContents).toContain('static ngInjectorDef: i0.InjectorDef');
});
});