feat(ivy): first steps towards JIT compilation (#23833)

This commit adds a mechanism by which the @angular/core annotations
for @Component, @Injectable, and @NgModule become decorators which,
when executed at runtime, trigger just-in-time compilation of their
associated types. The activation of these decorators is configured
by the ivy_switch mechanism, ensuring that the Ivy JIT engine does
not get included in Angular bundles unless specifically requested.

PR Close #23833
This commit is contained in:
Alex Rickabaugh
2018-05-09 08:35:25 -07:00
committed by Matias Niemelä
parent 1b6b936ef4
commit 919f42fea1
37 changed files with 1248 additions and 156 deletions

View File

@ -8,9 +8,9 @@
import {ChangeDetectionStrategy} from '../change_detection/constants';
import {Provider} from '../di';
import {R3_COMPILE_COMPONENT} from '../ivy_switch';
import {Type} from '../type';
import {TypeDecorator, makeDecorator, makePropDecorator} from '../util/decorators';
import {ViewEncapsulation} from './view';
@ -754,7 +754,8 @@ export interface Component extends Directive {
*/
export const Component: ComponentDecorator = makeDecorator(
'Component', (c: Component = {}) => ({changeDetection: ChangeDetectionStrategy.Default, ...c}),
Directive);
Directive, undefined,
(type: Type<any>, meta: Component) => (R3_COMPILE_COMPONENT || (() => {}))(type, meta));
/**
* Type of the Pipe decorator / constructor function.

View File

@ -9,9 +9,31 @@
import {InjectorDef, InjectorType, defineInjector} from '../di/defs';
import {convertInjectableProviderToFactory} from '../di/injectable';
import {Provider} from '../di/provider';
import {R3_COMPILE_NGMODULE} from '../ivy_switch';
import {Type} from '../type';
import {TypeDecorator, makeDecorator} from '../util/decorators';
export interface NgModuleDef<T> {
type: T;
bootstrap: Type<any>[];
declarations: Type<any>[];
imports: Type<any>[];
exports: Type<any>[];
transitiveCompileScope: {directives: any[]; pipes: any[];}|undefined;
}
export function defineNgModule<T>(def: {type: T} & Partial<NgModuleDef<T>>): never {
const res: NgModuleDef<T> = {
type: def.type,
bootstrap: def.bootstrap || [],
declarations: def.declarations || [],
imports: def.imports || [],
exports: def.exports || [],
transitiveCompileScope: undefined,
};
return res as never;
}
/**
* A wrapper around a module that also includes the providers.
@ -187,6 +209,19 @@ export interface NgModule {
id?: string;
}
function preR3NgModuleCompile(moduleType: InjectorType<any>, metadata: NgModule): void {
let imports = (metadata && metadata.imports) || [];
if (metadata && metadata.exports) {
imports = [...imports, metadata.exports];
}
moduleType.ngInjectorDef = defineInjector({
factory: convertInjectableProviderToFactory(moduleType, {useClass: moduleType}),
providers: metadata && metadata.providers,
imports: imports,
});
}
/**
* NgModule decorator and metadata.
*
@ -195,15 +230,4 @@ export interface NgModule {
*/
export const NgModule: NgModuleDecorator = makeDecorator(
'NgModule', (ngModule: NgModule) => ngModule, undefined, undefined,
(moduleType: InjectorType<any>, metadata: NgModule) => {
let imports = (metadata && metadata.imports) || [];
if (metadata && metadata.exports) {
imports = [...imports, metadata.exports];
}
moduleType.ngInjectorDef = defineInjector({
factory: convertInjectableProviderToFactory(moduleType, {useClass: moduleType}),
providers: metadata && metadata.providers,
imports: imports,
});
});
(type: Type<any>, meta: NgModule) => (R3_COMPILE_NGMODULE || preR3NgModuleCompile)(type, meta));