95 lines
3.3 KiB
TypeScript
Raw Normal View History

/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Expression, R3NgModuleMetadata, WrappedNodeExpr, compileNgModule as compileIvyNgModule, jitPatchDefinition} from '@angular/compiler';
import {ModuleWithProviders, NgModule, NgModuleDef} from '../../metadata/ng_module';
import {Type} from '../../type';
import {ComponentDef} from '../interfaces/definition';
import {flatten} from '../util';
import {angularCoreEnv} from './environment';
const EMPTY_ARRAY: Type<any>[] = [];
export function compileNgModule(type: Type<any>, ngModule: NgModule): void {
const meta: R3NgModuleMetadata = {
type: wrap(type),
bootstrap: flatten(ngModule.bootstrap || EMPTY_ARRAY).map(wrap),
declarations: flatten(ngModule.declarations || EMPTY_ARRAY).map(wrap),
imports: flatten(ngModule.imports || EMPTY_ARRAY).map(expandModuleWithProviders).map(wrap),
exports: flatten(ngModule.exports || EMPTY_ARRAY).map(expandModuleWithProviders).map(wrap),
emitInline: true,
};
const res = compileIvyNgModule(meta);
// Compute transitiveCompileScope
const transitiveCompileScope = {
directives: [] as any[],
pipes: [] as any[],
};
flatten(ngModule.declarations || EMPTY_ARRAY).forEach(decl => {
if (decl.ngPipeDef) {
transitiveCompileScope.pipes.push(decl);
} else if (decl.ngComponentDef) {
transitiveCompileScope.directives.push(decl);
patchComponentWithScope(decl, type as any);
} else {
transitiveCompileScope.directives.push(decl);
decl.ngSelectorScope = type;
}
});
function addExportsFrom(module: Type<any>& {ngModuleDef: NgModuleDef<any>}): void {
module.ngModuleDef.exports.forEach((exp: any) => {
if (isNgModule(exp)) {
addExportsFrom(exp);
} else if (exp.ngPipeDef) {
transitiveCompileScope.pipes.push(exp);
} else {
transitiveCompileScope.directives.push(exp);
}
});
}
flatten([(ngModule.imports || EMPTY_ARRAY), (ngModule.exports || EMPTY_ARRAY)])
.filter(importExport => isNgModule(importExport))
.forEach(mod => addExportsFrom(mod));
jitPatchDefinition(type, 'ngModuleDef', res.expression, angularCoreEnv);
((type as any).ngModuleDef as NgModuleDef<any>).transitiveCompileScope = transitiveCompileScope;
}
export function patchComponentWithScope<C, M>(
component: Type<C>& {ngComponentDef: ComponentDef<C>},
module: Type<M>& {ngModuleDef: NgModuleDef<M>}) {
component.ngComponentDef.directiveDefs = () =>
module.ngModuleDef.transitiveCompileScope !.directives.map(
dir => dir.ngDirectiveDef || dir.ngComponentDef);
component.ngComponentDef.pipeDefs = () =>
module.ngModuleDef.transitiveCompileScope !.pipes.map(pipe => pipe.ngPipeDef);
}
function expandModuleWithProviders(value: Type<any>| ModuleWithProviders): Type<any> {
if (isModuleWithProviders(value)) {
return value.ngModule;
}
return value;
}
function wrap(value: Type<any>): Expression {
return new WrappedNodeExpr(value);
}
function isModuleWithProviders(value: any): value is ModuleWithProviders {
return value.ngModule !== undefined;
}
function isNgModule(value: any): value is Type<any>&{ngModuleDef: NgModuleDef<any>} {
return value.ngModuleDef !== undefined;
}