feat(ivy): do not emit empty providers/imports for defineInjector (#29598)

The defineInjector function specifies its providers and imports array to
be optional, so if no providers/imports are present these keys may be
omitted. This commit updates the compiler to only generate the keys when
necessary.

PR Close #29598
This commit is contained in:
JoostK 2019-03-30 14:12:25 +01:00 committed by Jason Aden
parent 2d372f48db
commit 60afe88bcc
3 changed files with 20 additions and 10 deletions

View File

@ -158,10 +158,8 @@ export class NgModuleDecoratorHandler implements DecoratorHandler<NgModuleAnalys
schemas: [], schemas: [],
}; };
const providers: Expression = ngModule.has('providers') ?
new WrappedNodeExpr(ngModule.get('providers') !) :
new LiteralArrayExpr([]);
const rawProviders = ngModule.has('providers') ? ngModule.get('providers') ! : null; const rawProviders = ngModule.has('providers') ? ngModule.get('providers') ! : null;
const providers = rawProviders !== null ? new WrappedNodeExpr(rawProviders) : null;
// At this point, only add the module's imports as the injectors' imports. Any exported modules // At this point, only add the module's imports as the injectors' imports. Any exported modules
// are added during `resolve`, as we need scope information to be able to filter out directives // are added during `resolve`, as we need scope information to be able to filter out directives

View File

@ -445,6 +445,10 @@ describe('ngtsc behavioral tests', () => {
expect(jsContents).toContain('i0.ɵdefineNgModule({ type: TestModule, bootstrap: [TestCmp] });'); expect(jsContents).toContain('i0.ɵdefineNgModule({ type: TestModule, bootstrap: [TestCmp] });');
expect(jsContents) expect(jsContents)
.toContain('/*@__PURE__*/ i0.ɵsetNgModuleScope(TestModule, { declarations: [TestCmp] });'); .toContain('/*@__PURE__*/ i0.ɵsetNgModuleScope(TestModule, { declarations: [TestCmp] });');
expect(jsContents)
.toContain(
'i0.defineInjector({ factory: ' +
'function TestModule_Factory(t) { return new (t || TestModule)(); } });');
const dtsContents = env.getContents('test.d.ts'); const dtsContents = env.getContents('test.d.ts');
expect(dtsContents) expect(dtsContents)
@ -528,8 +532,8 @@ describe('ngtsc behavioral tests', () => {
expect(jsContents) expect(jsContents)
.toContain( .toContain(
'i0.defineInjector({ factory: function TestModule_Factory(t) ' + 'i0.defineInjector({ factory: function TestModule_Factory(t) ' +
'{ return new (t || TestModule)(); }, providers: [], ' + '{ return new (t || TestModule)(); }, imports: [[OtherModule, RouterModule.forRoot()],' +
'imports: [[OtherModule, RouterModule.forRoot()],\n OtherModule,\n RouterModule] });'); '\n OtherModule,\n RouterModule] });');
}); });
it('should compile NgModules with services without errors', () => { it('should compile NgModules with services without errors', () => {

View File

@ -190,7 +190,7 @@ export interface R3InjectorMetadata {
name: string; name: string;
type: o.Expression; type: o.Expression;
deps: R3DependencyMetadata[]|null; deps: R3DependencyMetadata[]|null;
providers: o.Expression; providers: o.Expression|null;
imports: o.Expression[]; imports: o.Expression[];
} }
@ -201,11 +201,19 @@ export function compileInjector(meta: R3InjectorMetadata): R3InjectorDef {
deps: meta.deps, deps: meta.deps,
injectFn: R3.inject, injectFn: R3.inject,
}); });
const expression = o.importExpr(R3.defineInjector).callFn([mapToMapExpression({ const definitionMap = {
factory: result.factory, factory: result.factory,
providers: meta.providers, } as{factory: o.Expression, providers: o.Expression, imports: o.Expression};
imports: o.literalArr(meta.imports),
})]); if (meta.providers !== null) {
definitionMap.providers = meta.providers;
}
if (meta.imports.length > 0) {
definitionMap.imports = o.literalArr(meta.imports);
}
const expression = o.importExpr(R3.defineInjector).callFn([mapToMapExpression(definitionMap)]);
const type = const type =
new o.ExpressionType(o.importExpr(R3.InjectorDef, [new o.ExpressionType(meta.type)])); new o.ExpressionType(o.importExpr(R3.InjectorDef, [new o.ExpressionType(meta.type)]));
return {expression, type, statements: result.statements}; return {expression, type, statements: result.statements};