refactor(core): change module semantics
This contains major changes to the compiler, bootstrap of the platforms and test environment initialization. Main part of #10043 Closes #10164 BREAKING CHANGE: - Semantics and name of `@AppModule` (now `@NgModule`) changed quite a bit. This is actually not breaking as `@AppModules` were not part of rc.4. We will have detailed docs on `@NgModule` separately. - `coreLoadAndBootstrap` and `coreBootstrap` can't be used any more (without migration support). Use `bootstrapModule` / `bootstrapModuleFactory` instead. - All Components listed in routes have to be part of the `declarations` of an NgModule. Either directly on the bootstrap module / lazy loaded module, or in an NgModule imported by them.
This commit is contained in:
@ -6,14 +6,15 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Injector} from '../di';
|
||||
import {Injector, OpaqueToken} from '../di';
|
||||
import {BaseException} from '../facade/exceptions';
|
||||
import {ConcreteType, Type, stringify} from '../facade/lang';
|
||||
import {ViewEncapsulation} from '../metadata';
|
||||
import {AppModuleMetadata} from '../metadata/app_module';
|
||||
import {NgModuleMetadata} from '../metadata/ng_module';
|
||||
|
||||
import {AppModuleFactory} from './app_module_factory';
|
||||
import {ComponentFactory} from './component_factory';
|
||||
import {ComponentResolver} from './component_resolver';
|
||||
import {NgModuleFactory} from './ng_module_factory';
|
||||
|
||||
|
||||
/**
|
||||
@ -32,14 +33,16 @@ export class ComponentStillLoadingError extends BaseException {
|
||||
* to create {@link ComponentFactory}s, which
|
||||
* can later be used to create and render a Component instance.
|
||||
*
|
||||
* Each `@AppModule` provides an own `Compiler` to its injector,
|
||||
* that will use the directives/pipes of the app module for compilation
|
||||
* Each `@NgModule` provides an own `Compiler` to its injector,
|
||||
* that will use the directives/pipes of the ng module for compilation
|
||||
* of components.
|
||||
* @stable
|
||||
*/
|
||||
export class Compiler {
|
||||
/**
|
||||
* Returns the injector with which the compiler has been created.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
get injector(): Injector {
|
||||
throw new BaseException(`Runtime compiler is not loaded. Tried to read the injector.`);
|
||||
@ -48,7 +51,8 @@ export class Compiler {
|
||||
/**
|
||||
* Loads the template and styles of a component and returns the associated `ComponentFactory`.
|
||||
*/
|
||||
compileComponentAsync<T>(component: ConcreteType<T>): Promise<ComponentFactory<T>> {
|
||||
compileComponentAsync<T>(component: ConcreteType<T>, ngModule: Type = null):
|
||||
Promise<ComponentFactory<T>> {
|
||||
throw new BaseException(
|
||||
`Runtime compiler is not loaded. Tried to compile ${stringify(component)}`);
|
||||
}
|
||||
@ -56,23 +60,21 @@ export class Compiler {
|
||||
* Compiles the given component. All templates have to be either inline or compiled via
|
||||
* `compileComponentAsync` before. Otherwise throws a {@link ComponentStillLoadingError}.
|
||||
*/
|
||||
compileComponentSync<T>(component: ConcreteType<T>): ComponentFactory<T> {
|
||||
compileComponentSync<T>(component: ConcreteType<T>, ngModule: Type = null): ComponentFactory<T> {
|
||||
throw new BaseException(
|
||||
`Runtime compiler is not loaded. Tried to compile ${stringify(component)}`);
|
||||
}
|
||||
/**
|
||||
* Compiles the given App Module. All templates of the components listed in `precompile`
|
||||
* Compiles the given NgModule. All templates of the components listed in `precompile`
|
||||
* have to be either inline or compiled before via `compileComponentAsync` /
|
||||
* `compileAppModuleAsync`. Otherwise throws a {@link ComponentStillLoadingError}.
|
||||
* `compileModuleAsync`. Otherwise throws a {@link ComponentStillLoadingError}.
|
||||
*/
|
||||
compileAppModuleSync<T>(moduleType: ConcreteType<T>, metadata: AppModuleMetadata = null):
|
||||
AppModuleFactory<T> {
|
||||
compileModuleSync<T>(moduleType: ConcreteType<T>): NgModuleFactory<T> {
|
||||
throw new BaseException(
|
||||
`Runtime compiler is not loaded. Tried to compile ${stringify(moduleType)}`);
|
||||
}
|
||||
|
||||
compileAppModuleAsync<T>(moduleType: ConcreteType<T>, metadata: AppModuleMetadata = null):
|
||||
Promise<AppModuleFactory<T>> {
|
||||
compileModuleAsync<T>(moduleType: ConcreteType<T>): Promise<NgModuleFactory<T>> {
|
||||
throw new BaseException(
|
||||
`Runtime compiler is not loaded. Tried to compile ${stringify(moduleType)}`);
|
||||
}
|
||||
@ -83,7 +85,7 @@ export class Compiler {
|
||||
clearCache(): void {}
|
||||
|
||||
/**
|
||||
* Clears the cache for the given component/appModule.
|
||||
* Clears the cache for the given component/ngModule.
|
||||
*/
|
||||
clearCacheFor(type: Type) {}
|
||||
}
|
||||
@ -98,8 +100,14 @@ export type CompilerOptions = {
|
||||
useJit?: boolean,
|
||||
defaultEncapsulation?: ViewEncapsulation,
|
||||
providers?: any[],
|
||||
deprecatedAppProviders?: any[]
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Token to provide CompilerOptions in the platform injector.
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
export const CompilerOptions = new OpaqueToken('compilerOptions');
|
||||
|
||||
/**
|
||||
* A factory for creating a Compiler
|
||||
@ -107,44 +115,5 @@ export type CompilerOptions = {
|
||||
* @experimental
|
||||
*/
|
||||
export abstract class CompilerFactory {
|
||||
static mergeOptions(defaultOptions: CompilerOptions = {}, newOptions: CompilerOptions = {}):
|
||||
CompilerOptions {
|
||||
return {
|
||||
useDebug: _firstDefined(newOptions.useDebug, defaultOptions.useDebug),
|
||||
useJit: _firstDefined(newOptions.useJit, defaultOptions.useJit),
|
||||
defaultEncapsulation:
|
||||
_firstDefined(newOptions.defaultEncapsulation, defaultOptions.defaultEncapsulation),
|
||||
providers: _mergeArrays(defaultOptions.providers, newOptions.providers),
|
||||
deprecatedAppProviders:
|
||||
_mergeArrays(defaultOptions.deprecatedAppProviders, newOptions.deprecatedAppProviders)
|
||||
};
|
||||
}
|
||||
|
||||
withDefaults(options: CompilerOptions = {}): CompilerFactory {
|
||||
return new _DefaultApplyingCompilerFactory(this, options);
|
||||
}
|
||||
abstract createCompiler(options?: CompilerOptions): Compiler;
|
||||
}
|
||||
|
||||
class _DefaultApplyingCompilerFactory extends CompilerFactory {
|
||||
constructor(private _delegate: CompilerFactory, private _options: CompilerOptions) { super(); }
|
||||
|
||||
createCompiler(options: CompilerOptions = {}): Compiler {
|
||||
return this._delegate.createCompiler(CompilerFactory.mergeOptions(this._options, options));
|
||||
}
|
||||
}
|
||||
|
||||
function _firstDefined<T>(...args: T[]): T {
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
if (args[i] !== undefined) {
|
||||
return args[i];
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function _mergeArrays(...parts: any[][]): any[] {
|
||||
let result: any[] = [];
|
||||
parts.forEach((part) => result.push.apply(result, part));
|
||||
return result;
|
||||
abstract createCompiler(options?: CompilerOptions[]): Compiler;
|
||||
}
|
||||
|
@ -6,12 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Console} from '../console';
|
||||
import {Injectable} from '../di/decorators';
|
||||
import {PromiseWrapper} from '../facade/async';
|
||||
import {BaseException} from '../facade/exceptions';
|
||||
import {Type, isBlank, isString, stringify} from '../facade/lang';
|
||||
import {reflector} from '../reflection/reflection';
|
||||
import {Type} from '../facade/lang';
|
||||
import {ComponentFactory} from './component_factory';
|
||||
|
||||
/**
|
||||
@ -19,43 +14,17 @@ import {ComponentFactory} from './component_factory';
|
||||
* can later be used to create and render a Component instance.
|
||||
*
|
||||
* @deprecated Use {@link ComponentFactoryResolver} together with {@link
|
||||
* AppModule}.precompile}/{@link Component}.precompile or
|
||||
* NgModule}.precompile}/{@link Component}.precompile or
|
||||
* {@link ANALYZE_FOR_PRECOMPILE} provider for dynamic component creation.
|
||||
* Use {@link AppModuleFactoryLoader} for lazy loading.
|
||||
* Use {@link NgModuleFactoryLoader} for lazy loading.
|
||||
*/
|
||||
export abstract class ComponentResolver {
|
||||
static DynamicCompilationDeprecationMsg =
|
||||
'ComponentResolver is deprecated for dynamic compilation. Use ComponentFactoryResolver together with @AppModule/@Component.precompile or ANALYZE_FOR_PRECOMPILE provider instead.';
|
||||
'ComponentResolver is deprecated for dynamic compilation. Use ComponentFactoryResolver together with @NgModule/@Component.precompile or ANALYZE_FOR_PRECOMPILE provider instead. For runtime compile only, you can also use Compiler.compileComponentSync/Async.';
|
||||
static LazyLoadingDeprecationMsg =
|
||||
'ComponentResolver is deprecated for lazy loading. Use AppModuleFactoryLoader instead.';
|
||||
'ComponentResolver is deprecated for lazy loading. Use NgModuleFactoryLoader instead.';
|
||||
|
||||
|
||||
abstract resolveComponent(component: Type|string): Promise<ComponentFactory<any>>;
|
||||
abstract clearCache(): void;
|
||||
}
|
||||
|
||||
function _isComponentFactory(type: any): boolean {
|
||||
return type instanceof ComponentFactory;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class ReflectorComponentResolver extends ComponentResolver {
|
||||
constructor(private _console: Console) { super(); }
|
||||
resolveComponent(component: Type|string): Promise<ComponentFactory<any>> {
|
||||
if (isString(component)) {
|
||||
return PromiseWrapper.reject(
|
||||
new BaseException(`Cannot resolve component using '${component}'.`), null);
|
||||
}
|
||||
this._console.warn(ComponentResolver.DynamicCompilationDeprecationMsg);
|
||||
|
||||
var metadatas = reflector.annotations(<Type>component);
|
||||
var componentFactory = metadatas.find(_isComponentFactory);
|
||||
|
||||
if (isBlank(componentFactory)) {
|
||||
throw new BaseException(`No precompiled component ${stringify(component)} found`);
|
||||
}
|
||||
return PromiseWrapper.resolve(componentFactory);
|
||||
}
|
||||
|
||||
clearCache() {}
|
||||
}
|
||||
|
@ -8,13 +8,15 @@
|
||||
|
||||
import {Injectable, Injector, ReflectiveInjector, ResolvedReflectiveProvider} from '../di';
|
||||
import {Type, isPresent} from '../facade/lang';
|
||||
|
||||
import {Compiler} from './compiler';
|
||||
import {ComponentRef} from './component_factory';
|
||||
import {ComponentResolver} from './component_resolver';
|
||||
import {ViewContainerRef} from './view_container_ref';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Use ComponentResolver and ViewContainerRef directly.
|
||||
* Use ComponentFactoryResolver and ViewContainerRef directly.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
@ -119,12 +121,12 @@ export abstract class DynamicComponentLoader {
|
||||
|
||||
@Injectable()
|
||||
export class DynamicComponentLoader_ extends DynamicComponentLoader {
|
||||
constructor(private _compiler: ComponentResolver) { super(); }
|
||||
constructor(private _compiler: Compiler) { super(); }
|
||||
|
||||
loadAsRoot(
|
||||
type: Type, overrideSelectorOrNode: string|any, injector: Injector, onDispose?: () => void,
|
||||
projectableNodes?: any[][]): Promise<ComponentRef<any>> {
|
||||
return this._compiler.resolveComponent(type).then(componentFactory => {
|
||||
return this._compiler.compileComponentAsync(<any>type).then(componentFactory => {
|
||||
var componentRef = componentFactory.create(
|
||||
injector, projectableNodes,
|
||||
isPresent(overrideSelectorOrNode) ? overrideSelectorOrNode : componentFactory.selector);
|
||||
@ -138,7 +140,7 @@ export class DynamicComponentLoader_ extends DynamicComponentLoader {
|
||||
loadNextToLocation(
|
||||
type: Type, location: ViewContainerRef, providers: ResolvedReflectiveProvider[] = null,
|
||||
projectableNodes: any[][] = null): Promise<ComponentRef<any>> {
|
||||
return this._compiler.resolveComponent(type).then(componentFactory => {
|
||||
return this._compiler.compileComponentAsync(<any>type).then(componentFactory => {
|
||||
var contextInjector = location.parentInjector;
|
||||
var childInjector = isPresent(providers) && providers.length > 0 ?
|
||||
ReflectiveInjector.fromResolvedProviders(providers, contextInjector) :
|
||||
|
@ -14,15 +14,16 @@ import {CodegenComponentFactoryResolver, ComponentFactoryResolver} from './compo
|
||||
|
||||
|
||||
/**
|
||||
* Represents an instance of an AppModule created via a {@link AppModuleFactory}.
|
||||
* Represents an instance of an NgModule created via a {@link NgModuleFactory}.
|
||||
*
|
||||
* `AppModuleRef` provides access to the AppModule Instance as well other objects related to this
|
||||
* AppModule Instance.
|
||||
* @stable
|
||||
* `NgModuleRef` provides access to the NgModule Instance as well other objects related to this
|
||||
* NgModule Instance.
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
export abstract class AppModuleRef<T> {
|
||||
export abstract class NgModuleRef<T> {
|
||||
/**
|
||||
* The injector that contains all of the providers of the AppModule.
|
||||
* The injector that contains all of the providers of the NgModule.
|
||||
*/
|
||||
get injector(): Injector { return unimplemented(); }
|
||||
|
||||
@ -33,22 +34,22 @@ export abstract class AppModuleRef<T> {
|
||||
get componentFactoryResolver(): ComponentFactoryResolver { return unimplemented(); }
|
||||
|
||||
/**
|
||||
* The AppModule instance.
|
||||
* The NgModule instance.
|
||||
*/
|
||||
get instance(): T { return unimplemented(); }
|
||||
}
|
||||
|
||||
/**
|
||||
* @stable
|
||||
* @experimental
|
||||
*/
|
||||
export class AppModuleFactory<T> {
|
||||
export class NgModuleFactory<T> {
|
||||
constructor(
|
||||
private _injectorClass: {new (parentInjector: Injector): AppModuleInjector<T>},
|
||||
private _injectorClass: {new (parentInjector: Injector): NgModuleInjector<T>},
|
||||
private _moduleype: ConcreteType<T>) {}
|
||||
|
||||
get moduleType(): ConcreteType<T> { return this._moduleype; }
|
||||
|
||||
create(parentInjector: Injector = null): AppModuleRef<T> {
|
||||
create(parentInjector: Injector): NgModuleRef<T> {
|
||||
if (!parentInjector) {
|
||||
parentInjector = Injector.NULL;
|
||||
}
|
||||
@ -60,9 +61,9 @@ export class AppModuleFactory<T> {
|
||||
|
||||
const _UNDEFINED = new Object();
|
||||
|
||||
export abstract class AppModuleInjector<T> extends CodegenComponentFactoryResolver implements
|
||||
export abstract class NgModuleInjector<T> extends CodegenComponentFactoryResolver implements
|
||||
Injector,
|
||||
AppModuleRef<T> {
|
||||
NgModuleRef<T> {
|
||||
public instance: T;
|
||||
|
||||
constructor(public parent: Injector, factories: ComponentFactory<any>[]) {
|
@ -6,12 +6,12 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {AppModuleFactory} from './app_module_factory';
|
||||
import {NgModuleFactory} from './ng_module_factory';
|
||||
|
||||
/**
|
||||
* Used to load app moduled factories.
|
||||
* Used to load ng moduled factories.
|
||||
* @experimental
|
||||
*/
|
||||
export abstract class AppModuleFactoryLoader {
|
||||
abstract load(path: string): Promise<AppModuleFactory<any>>;
|
||||
}
|
||||
export abstract class NgModuleFactoryLoader {
|
||||
abstract load(path: string): Promise<NgModuleFactory<any>>;
|
||||
}
|
@ -10,9 +10,9 @@
|
||||
import {Injectable, Optional} from '../di';
|
||||
import {global} from '../facade/lang';
|
||||
|
||||
import {AppModuleFactory} from './app_module_factory';
|
||||
import {AppModuleFactoryLoader} from './app_module_factory_loader';
|
||||
import {Compiler} from './compiler';
|
||||
import {NgModuleFactory} from './ng_module_factory';
|
||||
import {NgModuleFactoryLoader} from './ng_module_factory_loader';
|
||||
|
||||
const _SEPARATOR = '#';
|
||||
|
||||
@ -20,18 +20,18 @@ const FACTORY_MODULE_SUFFIX = '.ngfactory';
|
||||
const FACTORY_CLASS_SUFFIX = 'NgFactory';
|
||||
|
||||
/**
|
||||
* AppModuleFactoryLoader that uses SystemJS to load AppModuleFactory
|
||||
* NgModuleFactoryLoader that uses SystemJS to load NgModuleFactory
|
||||
* @experimental
|
||||
*/
|
||||
@Injectable()
|
||||
export class SystemJsAppModuleLoader implements AppModuleFactoryLoader {
|
||||
export class SystemJsNgModuleLoader implements NgModuleFactoryLoader {
|
||||
constructor(@Optional() private _compiler: Compiler) {}
|
||||
|
||||
load(path: string): Promise<AppModuleFactory<any>> {
|
||||
load(path: string): Promise<NgModuleFactory<any>> {
|
||||
return this._compiler ? this.loadAndCompile(path) : this.loadFactory(path);
|
||||
}
|
||||
|
||||
private loadAndCompile(path: string): Promise<AppModuleFactory<any>> {
|
||||
private loadAndCompile(path: string): Promise<NgModuleFactory<any>> {
|
||||
let [module, exportName] = path.split(_SEPARATOR);
|
||||
if (exportName === undefined) exportName = 'default';
|
||||
|
||||
@ -39,10 +39,10 @@ export class SystemJsAppModuleLoader implements AppModuleFactoryLoader {
|
||||
.System.import(module)
|
||||
.then((module: any) => module[exportName])
|
||||
.then((type: any) => checkNotEmpty(type, module, exportName))
|
||||
.then((type: any) => this._compiler.compileAppModuleAsync(type));
|
||||
.then((type: any) => this._compiler.compileModuleAsync(type));
|
||||
}
|
||||
|
||||
private loadFactory(path: string): Promise<AppModuleFactory<any>> {
|
||||
private loadFactory(path: string): Promise<NgModuleFactory<any>> {
|
||||
let [module, exportName] = path.split(_SEPARATOR);
|
||||
if (exportName === undefined) exportName = 'default';
|
||||
|
||||
@ -58,4 +58,4 @@ function checkNotEmpty(value: any, modulePath: string, exportName: string): any
|
||||
throw new Error(`Cannot find '${exportName}' in '${modulePath}'`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
@ -18,9 +18,9 @@ const _SEPARATOR = '#';
|
||||
/**
|
||||
* Component resolver that can load components lazily
|
||||
*
|
||||
* @deprecated Lazy loading of components is deprecated. Use {@link SystemJsAppModuleLoader} to lazy
|
||||
* @deprecated Lazy loading of components is deprecated. Use {@link SystemJsNgModuleLoader} to lazy
|
||||
* load
|
||||
* {@link AppModuleFactory}s instead.
|
||||
* {@link NgModuleFactory}s instead.
|
||||
*/
|
||||
@Injectable()
|
||||
export class SystemJsComponentResolver implements ComponentResolver {
|
||||
@ -53,9 +53,9 @@ const FACTORY_CLASS_SUFFIX = 'NgFactory';
|
||||
/**
|
||||
* Component resolver that can load component factories lazily
|
||||
*
|
||||
* @deprecated Lazy loading of components is deprecated. Use {@link SystemJsAppModuleLoader}
|
||||
* @deprecated Lazy loading of components is deprecated. Use {@link SystemJsNgModuleLoader}
|
||||
* to lazy
|
||||
* load {@link AppModuleFactory}s instead.
|
||||
* load {@link NgModuleFactory}s instead.
|
||||
*/
|
||||
@Injectable()
|
||||
export class SystemJsCmpFactoryResolver implements ComponentResolver {
|
||||
|
Reference in New Issue
Block a user