2016-06-23 09:47:54 -07:00
/**
* @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
*/
2016-04-28 17:50:03 -07:00
import { ListWrapper } from '../src/facade/collection' ;
2016-05-01 22:50:37 -07:00
import { BaseException , ExceptionHandler , unimplemented } from '../src/facade/exceptions' ;
2016-08-10 18:21:28 -07:00
import { isBlank , isPresent , isPromise , stringify } from '../src/facade/lang' ;
2016-06-08 16:38:52 -07:00
2016-08-02 07:54:14 -07:00
import { ApplicationInitStatus } from './application_init' ;
2016-08-02 07:38:14 -07:00
import { APP_BOOTSTRAP_LISTENER , PLATFORM_INITIALIZER } from './application_tokens' ;
2016-04-28 17:50:03 -07:00
import { ChangeDetectorRef } from './change_detection/change_detector_ref' ;
2016-06-08 16:38:52 -07:00
import { Console } from './console' ;
2016-08-11 15:24:35 -07:00
import { Injectable , Injector , OpaqueToken , Optional , ReflectiveInjector } from './di' ;
import { CompilerFactory , CompilerOptions } from './linker/compiler' ;
2016-06-08 16:38:52 -07:00
import { ComponentFactory , ComponentRef } from './linker/component_factory' ;
2016-06-30 13:07:17 -07:00
import { ComponentFactoryResolver } from './linker/component_factory_resolver' ;
2016-08-02 06:54:08 -07:00
import { NgModuleFactory , NgModuleInjector , NgModuleRef } from './linker/ng_module_factory' ;
2016-06-08 16:38:52 -07:00
import { WtfScopeFn , wtfCreateScope , wtfLeave } from './profile/profile' ;
import { Testability , TestabilityRegistry } from './testability/testability' ;
2016-08-10 18:21:28 -07:00
import { Type } from './type' ;
2016-06-08 16:38:52 -07:00
import { NgZone , NgZoneError } from './zone/ng_zone' ;
2016-06-17 14:09:19 -07:00
var _devMode : boolean = true ;
var _runModeLocked : boolean = false ;
2015-09-02 15:19:26 -07:00
var _platform : PlatformRef ;
2016-06-17 14:09:19 -07:00
/**
* Disable Angular's development mode, which turns off assertions and other
* checks within the framework.
*
* One important assertion this disables verifies that a change detection pass
* does not result in additional changes to any bindings (also known as
* unidirectional data flow).
2016-06-27 12:27:23 -07:00
*
* @experimental APIs related to application bootstrap are currently under review.
2016-06-17 14:09:19 -07:00
*/
export function enableProdMode ( ) : void {
if ( _runModeLocked ) {
// Cannot use BaseException as that ends up importing from facade/lang.
throw new BaseException ( 'Cannot enable prod mode after platform setup.' ) ;
}
_devMode = false ;
}
/**
2016-07-07 14:42:46 -07:00
* Returns whether Angular is in development mode. After called once,
* the value is locked and won't change any more.
*
* By default, this is true, unless a user calls `enableProdMode` before calling this.
2016-06-27 12:27:23 -07:00
*
* @experimental APIs related to application bootstrap are currently under review.
2016-06-17 14:09:19 -07:00
*/
2016-07-07 14:42:46 -07:00
export function isDevMode ( ) : boolean {
2016-06-17 14:09:19 -07:00
_runModeLocked = true ;
2016-07-07 14:42:46 -07:00
return _devMode ;
2016-06-17 14:09:19 -07:00
}
2015-11-13 11:21:16 -08:00
/**
2016-04-14 14:52:35 -07:00
* Creates a platform.
* Platforms have to be eagerly created via this function.
2016-06-27 12:27:23 -07:00
*
* @experimental APIs related to application bootstrap are currently under review.
2015-11-13 11:21:16 -08:00
*/
2016-04-14 14:52:35 -07:00
export function createPlatform ( injector : Injector ) : PlatformRef {
2016-08-12 14:46:45 -07:00
if ( isPresent ( _platform ) && ! _platform . destroyed ) {
2016-04-14 14:52:35 -07:00
throw new BaseException (
2016-06-08 16:38:52 -07:00
'There can be only one platform. Destroy the previous one to create a new one.' ) ;
2016-04-14 14:52:35 -07:00
}
2016-07-29 06:47:40 -07:00
_platform = injector . get ( PlatformRef ) ;
const inits : Function [ ] = < Function [ ] > injector . get ( PLATFORM_INITIALIZER , null ) ;
if ( isPresent ( inits ) ) inits . forEach ( init = > init ( ) ) ;
2016-04-14 14:52:35 -07:00
return _platform ;
}
2016-07-18 03:50:31 -07:00
/**
* Factory for a platform.
*
* @experimental
*/
export type PlatformFactory = ( extraProviders? : any [ ] ) = > PlatformRef ;
2016-07-08 10:47:17 -07:00
/**
2016-08-08 17:18:50 -07:00
* Creates a factory for a platform
2016-07-08 10:47:17 -07:00
*
* @experimental APIs related to application bootstrap are currently under review.
*/
2016-07-18 03:50:31 -07:00
export function createPlatformFactory (
parentPlaformFactory : PlatformFactory , name : string , providers : any [ ] = [ ] ) : PlatformFactory {
2016-07-08 10:47:17 -07:00
const marker = new OpaqueToken ( ` Platform: ${ name } ` ) ;
2016-07-18 03:50:31 -07:00
return ( extraProviders : any [ ] = [ ] ) = > {
2016-07-08 10:47:17 -07:00
if ( ! getPlatform ( ) ) {
2016-07-18 03:50:31 -07:00
if ( parentPlaformFactory ) {
parentPlaformFactory (
providers . concat ( extraProviders ) . concat ( { provide : marker , useValue : true } ) ) ;
} else {
createPlatform ( ReflectiveInjector . resolveAndCreate (
providers . concat ( extraProviders ) . concat ( { provide : marker , useValue : true } ) ) ) ;
}
2016-07-08 10:47:17 -07:00
}
return assertPlatform ( marker ) ;
} ;
}
2016-04-14 14:52:35 -07:00
/**
* Checks that there currently is a platform
* which contains the given token as a provider.
2016-06-27 12:27:23 -07:00
*
* @experimental APIs related to application bootstrap are currently under review.
2016-04-14 14:52:35 -07:00
*/
export function assertPlatform ( requiredToken : any ) : PlatformRef {
var platform = getPlatform ( ) ;
if ( isBlank ( platform ) ) {
2016-05-20 11:18:08 -07:00
throw new BaseException ( 'No platform exists!' ) ;
2016-04-14 14:52:35 -07:00
}
if ( isPresent ( platform ) && isBlank ( platform . injector . get ( requiredToken , null ) ) ) {
throw new BaseException (
'A platform with a different configuration has been created. Please destroy it first.' ) ;
}
return platform ;
2015-11-13 11:21:16 -08:00
}
2015-11-12 13:40:29 -08:00
2016-08-02 02:32:27 -07:00
/**
* Destroy the existing platform.
*
* @experimental APIs related to application bootstrap are currently under review.
*/
export function destroyPlatform ( ) : void {
if ( isPresent ( _platform ) && ! _platform . destroyed ) {
_platform . destroy ( ) ;
2015-11-18 09:18:37 -08:00
}
}
2016-04-14 14:52:35 -07:00
/**
* Returns the current platform.
2016-06-27 12:27:23 -07:00
*
* @experimental APIs related to application bootstrap are currently under review.
2016-04-14 14:52:35 -07:00
*/
export function getPlatform ( ) : PlatformRef {
2016-08-12 14:46:45 -07:00
return isPresent ( _platform ) && ! _platform . destroyed ? _platform : null ;
2015-09-02 15:19:26 -07:00
}
/**
2015-09-15 15:51:15 -07:00
* The Angular platform is the entry point for Angular on a web page. Each page
* has exactly one platform, and services (such as reflection) which are common
* to every Angular application running on the page are bound in its scope.
2015-08-20 17:18:27 -07:00
*
2015-09-15 15:51:15 -07:00
* A page's platform is initialized implicitly when {@link bootstrap}() is called, or
2016-04-14 14:52:35 -07:00
* explicitly by calling {@link createPlatform}().
2016-06-27 12:27:23 -07:00
*
* @experimental APIs related to application bootstrap are currently under review.
2015-08-20 17:18:27 -07:00
*/
2015-10-06 06:53:39 -07:00
export abstract class PlatformRef {
2015-10-26 10:50:25 -07:00
/**
2016-07-26 05:21:19 -07:00
* Creates an instance of an `@NgModule` for the given platform
* for offline compilation.
*
* ## Simple Example
*
* ```typescript
* my_module.ts:
*
* @NgModule({
* imports: [BrowserModule]
* })
* class MyModule {}
*
* main.ts:
* import {MyModuleNgFactory} from './my_module.ngfactory';
* import {browserPlatform} from '@angular/platform-browser';
*
* let moduleRef = browserPlatform().bootstrapModuleFactory(MyModuleNgFactory);
* ```
*
* @experimental APIs related to application bootstrap are currently under review.
*/
2016-07-29 06:47:40 -07:00
bootstrapModuleFactory < M > ( moduleFactory : NgModuleFactory < M > ) : Promise < NgModuleRef < M > > {
2016-07-26 05:21:19 -07:00
throw unimplemented ( ) ;
}
/**
* Creates an instance of an `@NgModule` for a given platform using the given runtime compiler.
*
* ## Simple Example
*
* ```typescript
* @NgModule({
* imports: [BrowserModule]
* })
* class MyModule {}
*
* let moduleRef = browserPlatform().bootstrapModule(MyModule);
* ```
* @stable
2015-10-26 10:50:25 -07:00
*/
2016-08-10 18:21:28 -07:00
bootstrapModule < M > ( moduleType : Type < M > , compilerOptions : CompilerOptions | CompilerOptions [ ] = [ ] ) :
Promise < NgModuleRef < M > > {
2016-07-26 05:21:19 -07:00
throw unimplemented ( ) ;
}
2016-08-02 02:32:27 -07:00
/**
* Register a listener to be called when the platform is disposed.
*/
abstract onDestroy ( callback : ( ) = > void ) : void ;
2015-09-02 15:19:26 -07:00
/**
2015-09-15 15:51:15 -07:00
* Retrieve the platform {@link Injector}, which is the parent injector for
2015-10-10 22:11:13 -07:00
* every Angular application on the page and provides singleton providers.
2015-09-02 15:19:26 -07:00
*/
2016-02-19 11:49:31 -08:00
get injector ( ) : Injector { throw unimplemented ( ) ; } ;
2015-08-20 17:18:27 -07:00
2016-08-02 02:32:27 -07:00
/**
* Destroy the Angular platform and all Angular applications on the page.
*/
abstract destroy ( ) : void ;
get destroyed ( ) : boolean { throw unimplemented ( ) ; }
2015-10-06 06:53:39 -07:00
}
2016-07-29 06:47:40 -07:00
function _callAndReportToExceptionHandler (
exceptionHandler : ExceptionHandler , callback : ( ) = > any ) : any {
try {
const result = callback ( ) ;
if ( isPromise ( result ) ) {
return result . catch ( ( e : any ) = > {
exceptionHandler . call ( e ) ;
// rethrow as the exception handler might not do it
throw e ;
} ) ;
} else {
return result ;
}
} catch ( e ) {
exceptionHandler . call ( e ) ;
// rethrow as the exception handler might not do it
throw e ;
}
}
2016-04-14 14:52:35 -07:00
@Injectable ( )
2015-10-06 06:53:39 -07:00
export class PlatformRef_ extends PlatformRef {
2016-08-02 02:32:27 -07:00
private _modules : NgModuleRef < any > [ ] = [ ] ;
private _destroyListeners : Function [ ] = [ ] ;
2015-10-06 06:53:39 -07:00
2016-08-02 02:32:27 -07:00
private _destroyed : boolean = false ;
2015-10-06 06:53:39 -07:00
2016-07-29 06:47:40 -07:00
constructor ( private _injector : Injector ) { super ( ) ; }
2015-10-06 06:53:39 -07:00
2016-08-02 02:32:27 -07:00
/**
* @deprecated
*/
registerDisposeListener ( dispose : ( ) = > void ) : void { this . onDestroy ( dispose ) ; }
onDestroy ( callback : ( ) = > void ) : void { this . _destroyListeners . push ( callback ) ; }
2015-09-02 15:19:26 -07:00
2016-04-14 14:52:35 -07:00
get injector ( ) : Injector { return this . _injector ; }
2015-09-02 15:19:26 -07:00
2016-08-02 02:32:27 -07:00
/**
* @deprecated
*/
get disposed() { return this . destroyed ; }
get destroyed() { return this . _destroyed ; }
2016-04-14 14:52:35 -07:00
2016-08-02 02:32:27 -07:00
destroy() {
if ( this . _destroyed ) {
2016-08-02 07:54:14 -07:00
throw new BaseException ( 'The platform has already been destroyed!' ) ;
2016-08-02 02:32:27 -07:00
}
ListWrapper . clone ( this . _modules ) . forEach ( ( app ) = > app . destroy ( ) ) ;
this . _destroyListeners . forEach ( ( dispose ) = > dispose ( ) ) ;
this . _destroyed = true ;
2015-09-02 15:19:26 -07:00
}
2016-08-02 02:32:27 -07:00
/**
* @deprecated
*/
dispose ( ) : void { this . destroy ( ) ; }
2016-07-26 05:21:19 -07:00
2016-07-29 06:47:40 -07:00
bootstrapModuleFactory < M > ( moduleFactory : NgModuleFactory < M > ) : Promise < NgModuleRef < M > > {
2016-08-05 13:32:04 -07:00
return this . _bootstrapModuleFactoryWithZone ( moduleFactory , null ) ;
}
private _bootstrapModuleFactoryWithZone < M > ( moduleFactory : NgModuleFactory < M > , ngZone : NgZone ) :
Promise < NgModuleRef < M > > {
2016-07-26 05:21:19 -07:00
// Note: We need to create the NgZone _before_ we instantiate the module,
// as instantiating the module creates some providers eagerly.
// So we create a mini parent injector that just contains the new NgZone and
// pass that as parent to the NgModuleFactory.
2016-08-05 13:32:04 -07:00
if ( ! ngZone ) ngZone = new NgZone ( { enableLongStackTrace : isDevMode ( ) } ) ;
2016-07-29 06:47:40 -07:00
// Attention: Don't use ApplicationRef.run here,
// as we want to be sure that all possible constructor calls are inside `ngZone.run`!
return ngZone . run ( ( ) = > {
const ngZoneInjector =
ReflectiveInjector . resolveAndCreate ( [ { provide : NgZone , useValue : ngZone } ] , this . injector ) ;
2016-08-02 06:54:08 -07:00
const moduleRef = < NgModuleInjector < M > > moduleFactory . create ( ngZoneInjector ) ;
2016-07-29 14:45:05 -07:00
const exceptionHandler : ExceptionHandler = moduleRef . injector . get ( ExceptionHandler , null ) ;
if ( ! exceptionHandler ) {
throw new Error ( 'No ExceptionHandler. Is platform module (BrowserModule) included?' ) ;
}
2016-08-02 02:32:27 -07:00
moduleRef . onDestroy ( ( ) = > ListWrapper . remove ( this . _modules , moduleRef ) ) ;
2016-08-02 15:53:34 -07:00
ngZone . onError . subscribe ( {
next : ( error : NgZoneError ) = > { exceptionHandler . call ( error . error , error . stackTrace ) ; }
2016-07-29 06:47:40 -07:00
} ) ;
return _callAndReportToExceptionHandler ( exceptionHandler , ( ) = > {
2016-08-02 07:54:14 -07:00
const initStatus : ApplicationInitStatus = moduleRef . injector . get ( ApplicationInitStatus ) ;
2016-08-02 07:38:14 -07:00
return initStatus . donePromise . then ( ( ) = > {
2016-08-02 06:54:08 -07:00
this . _moduleDoBootstrap ( moduleRef ) ;
2016-07-29 06:47:40 -07:00
return moduleRef ;
} ) ;
} ) ;
} ) ;
2016-07-26 05:21:19 -07:00
}
2016-08-10 18:21:28 -07:00
bootstrapModule < M > ( moduleType : Type < M > , compilerOptions : CompilerOptions | CompilerOptions [ ] = [ ] ) :
Promise < NgModuleRef < M > > {
2016-08-05 13:32:04 -07:00
return this . _bootstrapModuleWithZone ( moduleType , compilerOptions , null ) ;
}
private _bootstrapModuleWithZone < M > (
2016-08-10 18:21:28 -07:00
moduleType : Type < M > , compilerOptions : CompilerOptions | CompilerOptions [ ] = [ ] ,
2016-08-05 13:32:04 -07:00
ngZone : NgZone ) : Promise < NgModuleRef < M > > {
2016-07-26 05:21:19 -07:00
const compilerFactory : CompilerFactory = this . injector . get ( CompilerFactory ) ;
const compiler = compilerFactory . createCompiler (
compilerOptions instanceof Array ? compilerOptions : [ compilerOptions ] ) ;
return compiler . compileModuleAsync ( moduleType )
2016-08-05 13:32:04 -07:00
. then ( ( moduleFactory ) = > this . _bootstrapModuleFactoryWithZone ( moduleFactory , ngZone ) ) ;
2016-07-26 05:21:19 -07:00
}
2016-08-02 06:54:08 -07:00
private _moduleDoBootstrap ( moduleRef : NgModuleInjector < any > ) {
const appRef = moduleRef . injector . get ( ApplicationRef ) ;
if ( moduleRef . bootstrapFactories . length > 0 ) {
moduleRef . bootstrapFactories . forEach ( ( compFactory ) = > appRef . bootstrap ( compFactory ) ) ;
} else if ( moduleRef . instance . ngDoBootstrap ) {
moduleRef . instance . ngDoBootstrap ( appRef ) ;
} else {
throw new BaseException (
` The module ${ stringify ( moduleRef . instance . constructor ) } was bootstrapped, but it does not declare "@NgModule.bootstrap" components nor a "ngDoBootstrap" method. ` +
` Please define one of these. ` ) ;
}
}
2015-09-02 15:19:26 -07:00
}
/**
2015-09-15 15:51:15 -07:00
* A reference to an Angular application running on a page.
2015-09-02 15:19:26 -07:00
*
2015-09-15 15:51:15 -07:00
* For more about Angular applications, see the documentation for {@link bootstrap}.
2016-06-27 12:27:23 -07:00
*
* @experimental APIs related to application bootstrap are currently under review.
2015-09-02 15:19:26 -07:00
*/
2015-10-06 06:53:39 -07:00
export abstract class ApplicationRef {
2015-08-20 17:18:27 -07:00
/**
2015-09-15 15:51:15 -07:00
* Bootstrap a new component at the root level of the application.
*
2015-11-17 09:41:31 -08:00
* ### Bootstrap process
2015-09-15 15:51:15 -07:00
*
* When bootstrapping a new root component into an application, Angular mounts the
* specified application component onto DOM elements identified by the [componentType]'s
* selector and kicks off automatic change detection to finish initializing the component.
*
2015-10-19 15:37:32 +01:00
* ### Example
2015-11-30 08:28:54 -08:00
* {@example core/ts/platform/platform.ts region='longform'}
2015-09-02 15:19:26 -07:00
*/
2016-08-10 18:21:28 -07:00
abstract bootstrap < C > ( componentFactory : ComponentFactory < C > | Type < C > ) : ComponentRef < C > ;
2015-10-06 06:53:39 -07:00
2015-10-28 10:34:13 -07:00
/**
* Invoke this method to explicitly process change detection and its side-effects.
*
* In development mode, `tick()` also performs a second change detection cycle to ensure that no
* further changes are detected. If additional changes are picked up during this second cycle,
* bindings in the app have side-effects that cannot be resolved in a single change detection
* pass.
* In this case, Angular throws an error, since an Angular application can only have one change
* detection pass during which all change detection must complete.
*/
abstract tick ( ) : void ;
2015-10-09 16:22:07 -07:00
/**
* Get a list of component types registered to this application.
2016-08-02 07:49:33 -07:00
* This list is populated even before the component is created.
2015-10-09 16:22:07 -07:00
*/
2016-08-10 18:21:28 -07:00
get componentTypes ( ) : Type < any > [ ] { return < Type < any > [ ] > unimplemented ( ) ; } ;
2016-08-02 07:49:33 -07:00
2016-08-02 06:54:08 -07:00
/**
* Get a list of components registered to this application.
*/
get components ( ) : ComponentRef < any > [ ] { return < ComponentRef < any > [ ] > unimplemented ( ) ; } ;
2015-10-06 06:53:39 -07:00
}
2016-04-14 14:52:35 -07:00
@Injectable ( )
2015-10-06 06:53:39 -07:00
export class ApplicationRef_ extends ApplicationRef {
2015-10-28 10:34:13 -07:00
/** @internal */
static _tickScope : WtfScopeFn = wtfCreateScope ( 'ApplicationRef#tick()' ) ;
2015-10-06 06:53:39 -07:00
private _bootstrapListeners : Function [ ] = [ ] ;
2016-04-30 10:52:04 -07:00
private _rootComponents : ComponentRef < any > [ ] = [ ] ;
2016-08-10 18:21:28 -07:00
private _rootComponentTypes : Type < any > [ ] = [ ] ;
2015-10-28 10:34:13 -07:00
private _changeDetectorRefs : ChangeDetectorRef [ ] = [ ] ;
private _runningTick : boolean = false ;
private _enforceNoNewChanges : boolean = false ;
2015-10-06 06:53:39 -07:00
2016-06-30 13:07:17 -07:00
constructor (
2016-08-02 02:32:27 -07:00
private _zone : NgZone , private _console : Console , private _injector : Injector ,
private _exceptionHandler : ExceptionHandler ,
2016-06-30 13:07:17 -07:00
private _componentFactoryResolver : ComponentFactoryResolver ,
2016-08-02 07:54:14 -07:00
private _initStatus : ApplicationInitStatus ,
2016-06-30 13:07:17 -07:00
@Optional ( ) private _testabilityRegistry : TestabilityRegistry ,
2016-07-29 06:47:40 -07:00
@Optional ( ) private _testability : Testability ) {
2015-10-06 06:53:39 -07:00
super ( ) ;
2016-06-17 14:09:19 -07:00
this . _enforceNoNewChanges = isDevMode ( ) ;
2016-08-02 15:53:34 -07:00
this . _zone . onMicrotaskEmpty . subscribe (
{ next : ( ) = > { this . _zone . run ( ( ) = > { this . tick ( ) ; } ) ; } } ) ;
2015-10-06 06:53:39 -07:00
}
2015-10-28 10:34:13 -07:00
registerChangeDetector ( changeDetector : ChangeDetectorRef ) : void {
this . _changeDetectorRefs . push ( changeDetector ) ;
}
2015-11-10 10:40:33 -08:00
unregisterChangeDetector ( changeDetector : ChangeDetectorRef ) : void {
ListWrapper . remove ( this . _changeDetectorRefs , changeDetector ) ;
}
2016-08-10 18:21:28 -07:00
bootstrap < C > ( componentOrFactory : ComponentFactory < C > | Type < C > ) : ComponentRef < C > {
2016-08-02 07:38:14 -07:00
if ( ! this . _initStatus . done ) {
throw new BaseException (
'Cannot bootstrap as there are still asynchronous initializers running. Bootstrap components in the `ngDoBootstrap` method of the root module.' ) ;
}
2016-08-02 07:48:15 -07:00
let componentFactory : ComponentFactory < C > ;
if ( componentOrFactory instanceof ComponentFactory ) {
componentFactory = componentOrFactory ;
} else {
componentFactory = this . _componentFactoryResolver . resolveComponentFactory ( componentOrFactory ) ;
}
this . _rootComponentTypes . push ( componentFactory . componentType ) ;
var compRef = componentFactory . create ( this . _injector , [ ] , componentFactory . selector ) ;
compRef . onDestroy ( ( ) = > { this . _unloadComponent ( compRef ) ; } ) ;
var testability = compRef . injector . get ( Testability , null ) ;
if ( isPresent ( testability ) ) {
compRef . injector . get ( TestabilityRegistry )
. registerApplication ( compRef . location . nativeElement , testability ) ;
}
2016-04-14 14:52:35 -07:00
2016-08-02 07:48:15 -07:00
this . _loadComponent ( compRef ) ;
if ( isDevMode ( ) ) {
this . _console . log (
` Angular 2 is running in the development mode. Call enableProdMode() to enable the production mode. ` ) ;
}
return compRef ;
2015-09-02 15:19:26 -07:00
}
2015-11-10 10:40:33 -08:00
/** @internal */
2016-04-30 10:52:04 -07:00
_loadComponent ( componentRef : ComponentRef < any > ) : void {
2016-04-13 17:05:17 -07:00
this . _changeDetectorRefs . push ( componentRef . changeDetectorRef ) ;
2015-11-10 10:40:33 -08:00
this . tick ( ) ;
2016-02-11 17:01:17 -08:00
this . _rootComponents . push ( componentRef ) ;
2016-08-02 05:22:44 -07:00
// Get the listeners lazily to prevent DI cycles.
const listeners =
< ( ( compRef : ComponentRef < any > ) = > void ) [ ] > this . _injector . get ( APP_BOOTSTRAP_LISTENER , [ ] )
. concat ( this . _bootstrapListeners ) ;
listeners . forEach ( ( listener ) = > listener ( componentRef ) ) ;
2015-11-10 10:40:33 -08:00
}
/** @internal */
2016-04-30 10:52:04 -07:00
_unloadComponent ( componentRef : ComponentRef < any > ) : void {
2016-02-11 17:01:17 -08:00
if ( ! ListWrapper . contains ( this . _rootComponents , componentRef ) ) {
2015-11-10 10:40:33 -08:00
return ;
}
2016-04-13 17:05:17 -07:00
this . unregisterChangeDetector ( componentRef . changeDetectorRef ) ;
2016-02-11 17:01:17 -08:00
ListWrapper . remove ( this . _rootComponents , componentRef ) ;
2015-11-10 10:40:33 -08:00
}
2015-10-28 10:34:13 -07:00
tick ( ) : void {
if ( this . _runningTick ) {
2016-06-08 16:38:52 -07:00
throw new BaseException ( 'ApplicationRef.tick is called recursively' ) ;
2015-10-28 10:34:13 -07:00
}
var s = ApplicationRef_ . _tickScope ( ) ;
try {
this . _runningTick = true ;
this . _changeDetectorRefs . forEach ( ( detector ) = > detector . detectChanges ( ) ) ;
if ( this . _enforceNoNewChanges ) {
this . _changeDetectorRefs . forEach ( ( detector ) = > detector . checkNoChanges ( ) ) ;
}
} finally {
this . _runningTick = false ;
wtfLeave ( s ) ;
}
}
2016-08-02 02:32:27 -07:00
ngOnDestroy() {
2015-09-02 15:19:26 -07:00
// TODO(alxhub): Dispose of the NgZone.
2016-04-13 17:05:17 -07:00
ListWrapper . clone ( this . _rootComponents ) . forEach ( ( ref ) = > ref . destroy ( ) ) ;
2015-09-02 15:19:26 -07:00
}
2015-10-09 16:22:07 -07:00
2016-08-10 18:21:28 -07:00
get componentTypes ( ) : Type < any > [ ] { return this . _rootComponentTypes ; }
2016-08-02 06:54:08 -07:00
get components ( ) : ComponentRef < any > [ ] { return this . _rootComponents ; }
2015-08-20 17:18:27 -07:00
}