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

@ -83,7 +83,7 @@ export * from './injectable_compiler_2';
export * from './render3/view/api';
export {jitExpression} from './render3/r3_jit';
export {R3DependencyMetadata, R3FactoryMetadata, R3ResolvedDependencyType} from './render3/r3_factory';
export {compileNgModule, R3NgModuleMetadata} from './render3/r3_module_compiler';
export {compileInjector, compileNgModule, R3InjectorMetadata, R3NgModuleMetadata} from './render3/r3_module_compiler';
export {makeBindingParser, parseTemplate} from './render3/view/template';
export {compileComponentFromMetadata, compileDirectiveFromMetadata, parseHostBindings} from './render3/view/compiler';
// This file only reexports content of the `src` folder. Keep it that way.

View File

@ -114,6 +114,11 @@ export class Identifiers {
moduleName: CORE,
};
static InjectorDef: o.ExternalReference = {
name: 'InjectorDef',
moduleName: CORE,
};
static defineInjector: o.ExternalReference = {
name: 'defineInjector',
moduleName: CORE,

View File

@ -13,6 +13,7 @@ import {mapLiteral} from '../output/map_util';
import * as o from '../output/output_ast';
import {OutputContext} from '../util';
import {R3DependencyMetadata, compileFactoryFunction} from './r3_factory';
import {Identifiers as R3} from './r3_identifiers';
import {convertMetaToOutput, mapToMapExpression} from './util';
@ -81,6 +82,35 @@ export function compileNgModule(meta: R3NgModuleMetadata): R3NgModuleDef {
return {expression, type, additionalStatements};
}
export interface R3InjectorDef {
expression: o.Expression;
type: o.Type;
}
export interface R3InjectorMetadata {
name: string;
type: o.Expression;
deps: R3DependencyMetadata[];
providers: o.Expression;
imports: o.Expression;
}
export function compileInjector(meta: R3InjectorMetadata): R3InjectorDef {
const expression = o.importExpr(R3.defineInjector).callFn([mapToMapExpression({
factory: compileFactoryFunction({
name: meta.name,
fnOrClass: meta.type,
deps: meta.deps,
useNew: true,
injectFn: R3.inject,
}),
providers: meta.providers,
imports: meta.imports,
})]);
const type = new o.ExpressionType(o.importExpr(R3.InjectorDef));
return {expression, type};
}
// TODO(alxhub): integrate this with `compileNgModule`. Currently the two are separate operations.
export function compileNgModuleFromRender2(
ctx: OutputContext, ngModule: CompileShallowModuleMetadata,