feat(compiler): support sync runtime compile

Adds new abstraction `Compiler` with methods
`compileComponentAsync` and `compileComponentSync`.
This is in preparation of deprecating `ComponentResolver`.

`compileComponentSync` is able to compile components
synchronously given all components either have an inline
template or they have been compiled before.

Also changes `TestComponentBuilder.createSync` to
take a `Type` and use the new `compileComponentSync` method.

Also supports overriding the component metadata even if
the component has already been compiled.

Also fixes #7084 in a better way.

BREAKING CHANGE:
`TestComponentBuilder.createSync` now takes a component type
and throws if not all templates are either inlined
are compiled before via `createAsync`.

Closes #9594
This commit is contained in:
Tobias Bosch
2016-06-24 08:46:43 -07:00
parent 24eb8389d2
commit bf598d6b8b
35 changed files with 1093 additions and 700 deletions

View File

@ -6,14 +6,15 @@
* found in the LICENSE file at https://angular.io/license
*/
import {AnimationEntryMetadata, ComponentFactory, ComponentResolver, Injectable, Injector, NgZone, OpaqueToken, ViewMetadata} from '../index';
import {AnimationEntryMetadata, Compiler, ComponentFactory, Injectable, Injector, NgZone, OpaqueToken, ViewMetadata} from '../index';
import {PromiseWrapper} from '../src/facade/async';
import {IS_DART, Type, isPresent} from '../src/facade/lang';
import {ConcreteType, IS_DART, Type, isPresent} from '../src/facade/lang';
import {ComponentFixture} from './component_fixture';
import {tick} from './fake_async';
/**
* An abstract class for inserting the root test component element in a platform independent way.
*
@ -118,20 +119,21 @@ export class TestComponentBuilder {
/**
* Builds and returns a ComponentFixture.
*/
createAsync(rootComponentType: Type): Promise<ComponentFixture<any>> {
createAsync<T>(rootComponentType: ConcreteType<T>): Promise<ComponentFixture<T>> {
let noNgZone = IS_DART || this._injector.get(ComponentFixtureNoNgZone, false);
let ngZone: NgZone = noNgZone ? null : this._injector.get(NgZone, null);
let compiler: Compiler = this._injector.get(Compiler);
let initComponent = () => {
let promise: Promise<ComponentFactory<any>> =
this._injector.get(ComponentResolver).resolveComponent(rootComponentType);
compiler.compileComponentAsync(rootComponentType);
return promise.then(componentFactory => this.createFromFactory(ngZone, componentFactory));
};
return ngZone == null ? initComponent() : ngZone.run(initComponent);
}
createFakeAsync(rootComponentType: Type): ComponentFixture<any> {
createFakeAsync<T>(rootComponentType: ConcreteType<T>): ComponentFixture<T> {
let result: any /** TODO #9100 */;
let error: any /** TODO #9100 */;
PromiseWrapper.then(
@ -144,15 +146,16 @@ export class TestComponentBuilder {
return result;
}
/**
* @deprecated createSync will be replaced with the ability to precompile components from within
* the test.
*/
createSync<C>(componentFactory: ComponentFactory<C>): ComponentFixture<C> {
createSync<T>(rootComponentType: ConcreteType<T>): ComponentFixture<T> {
let noNgZone = IS_DART || this._injector.get(ComponentFixtureNoNgZone, false);
let ngZone: NgZone = noNgZone ? null : this._injector.get(NgZone, null);
let compiler: Compiler = this._injector.get(Compiler);
let initComponent = () => {
return this.createFromFactory(
ngZone, this._injector.get(Compiler).compileComponentSync(rootComponentType));
};
let initComponent = () => this.createFromFactory(ngZone, componentFactory);
return ngZone == null ? initComponent() : ngZone.run(initComponent);
}
}