2016-06-23 12:47:54 -04: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
* /
2017-02-03 08:42:22 -05:00
import { Observable } from 'rxjs/Observable' ;
import { Observer } from 'rxjs/Observer' ;
import { Subscription } from 'rxjs/Subscription' ;
import { merge } from 'rxjs/observable/merge' ;
import { share } from 'rxjs/operator/share' ;
2017-03-14 19:26:17 -04:00
2016-08-25 03:50:16 -04:00
import { ErrorHandler } from '../src/error_handler' ;
2017-03-02 12:37:01 -05:00
import { scheduleMicroTask , stringify } from '../src/util' ;
2016-09-18 18:55:08 -04:00
import { isPromise } from '../src/util/lang' ;
2017-03-14 19:26:17 -04:00
2016-08-02 10:54:14 -04:00
import { ApplicationInitStatus } from './application_init' ;
2016-08-02 10:38:14 -04:00
import { APP_BOOTSTRAP_LISTENER , PLATFORM_INITIALIZER } from './application_tokens' ;
2016-06-08 19:38:52 -04:00
import { Console } from './console' ;
2017-03-14 19:26:17 -04:00
import { Injectable , InjectionToken , Injector , Provider , ReflectiveInjector } from './di' ;
2016-08-11 18:24:35 -04:00
import { CompilerFactory , CompilerOptions } from './linker/compiler' ;
2016-06-08 19:38:52 -04:00
import { ComponentFactory , ComponentRef } from './linker/component_factory' ;
2017-03-14 19:26:17 -04:00
import { ComponentFactoryBoundToModule , ComponentFactoryResolver } from './linker/component_factory_resolver' ;
2017-05-11 13:26:02 -04:00
import { InternalNgModuleRef , NgModuleFactory , NgModuleRef } from './linker/ng_module_factory' ;
2017-02-17 11:56:49 -05:00
import { InternalViewRef , ViewRef } from './linker/view_ref' ;
2016-06-08 19:38:52 -04:00
import { WtfScopeFn , wtfCreateScope , wtfLeave } from './profile/profile' ;
import { Testability , TestabilityRegistry } from './testability/testability' ;
2016-08-10 21:21:28 -04:00
import { Type } from './type' ;
2016-08-15 19:10:30 -04:00
import { NgZone } from './zone/ng_zone' ;
2016-06-08 19:38:52 -04:00
2016-09-20 17:14:57 -04:00
let _devMode : boolean = true ;
let _runModeLocked : boolean = false ;
let _platform : PlatformRef ;
2015-09-02 18:19:26 -04:00
2017-02-12 12:16:23 -05:00
export const ALLOW_MULTIPLE_PLATFORMS = new InjectionToken < boolean > ( 'AllowMultipleToken' ) ;
2016-06-17 17:09:19 -04: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 15:27:23 -04:00
*
2016-08-24 01:29:34 -04:00
* @stable
2016-06-17 17:09:19 -04:00
* /
export function enableProdMode ( ) : void {
if ( _runModeLocked ) {
2016-08-25 03:50:16 -04:00
throw new Error ( 'Cannot enable prod mode after platform setup.' ) ;
2016-06-17 17:09:19 -04:00
}
_devMode = false ;
}
/ * *
2016-07-07 17:42:46 -04: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 15:27:23 -04:00
*
* @experimental APIs related to application bootstrap are currently under review .
2016-06-17 17:09:19 -04:00
* /
2016-07-07 17:42:46 -04:00
export function isDevMode ( ) : boolean {
2016-06-17 17:09:19 -04:00
_runModeLocked = true ;
2016-07-07 17:42:46 -04:00
return _devMode ;
2016-06-17 17:09:19 -04:00
}
2016-11-09 17:58:40 -05:00
/ * *
* A token for third - party components that can register themselves with NgProbe .
*
* @experimental
* /
export class NgProbeToken {
constructor ( public name : string , public token : any ) { }
}
2015-11-13 14:21:16 -05:00
/ * *
2016-04-14 17:52:35 -04:00
* Creates a platform .
* Platforms have to be eagerly created via this function .
2016-06-27 15:27:23 -04:00
*
* @experimental APIs related to application bootstrap are currently under review .
2015-11-13 14:21:16 -05:00
* /
2016-04-14 17:52:35 -04:00
export function createPlatform ( injector : Injector ) : PlatformRef {
2017-02-12 12:16:23 -05:00
if ( _platform && ! _platform . destroyed &&
! _platform . injector . get ( ALLOW_MULTIPLE_PLATFORMS , false ) ) {
2016-08-25 03:50:16 -04:00
throw new Error (
2016-06-08 19:38:52 -04:00
'There can be only one platform. Destroy the previous one to create a new one.' ) ;
2016-04-14 17:52:35 -04:00
}
2016-07-29 09:47:40 -04:00
_platform = injector . get ( PlatformRef ) ;
2017-01-03 19:54:46 -05:00
const inits = injector . get ( PLATFORM_INITIALIZER , null ) ;
2017-04-14 17:40:56 -04:00
if ( inits ) inits . forEach ( ( init : any ) = > init ( ) ) ;
2016-04-14 17:52:35 -04:00
return _platform ;
}
refactor(core): clean up platform bootstrap and initTestEnvironment
- Introduces `CompilerFactory` which can be part of a `PlatformRef`.
- Introduces `WorkerAppModule`, `WorkerUiModule`, `ServerModule`
- Introduces `serverDynamicPlatform` for applications using runtime compilation
on the server.
- Changes browser bootstrap for runtime and offline compilation (see below for an example).
* introduces `bootstrapModule` and `bootstrapModuleFactory` in `@angular/core`
* introduces new `browserDynamicPlatform` in `@angular/platform-browser-dynamic
- Changes `initTestEnvironment` (which used to be `setBaseTestProviders`) to not take a compiler factory any more (see below for an example).
BREAKING CHANGE:
## Migration from `setBaseTestProviders` to `initTestEnvironment`:
- For the browser platform:
BEFORE:
```
import {setBaseTestProviders} from ‘@angular/core/testing’;
import {TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS} from ‘@angular/platform-browser-dynamic/testing’;
setBaseTestProviders(TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS);
```
AFTER:
```
import {initTestEnvironment} from ‘@angular/core/testing’;
import {browserDynamicTestPlatform,
BrowserDynamicTestModule} from ‘@angular/platform-browser-dynamic/testing’;
initTestEnvironment(
BrowserDynamicTestModule,
browserDynamicTestPlatform());
```
- For the server platform:
BEFORE:
```
import {setBaseTestProviders} from ‘@angular/core/testing’;
import {TEST_SERVER_PLATFORM_PROVIDERS,
TEST_SERVER_APPLICATION_PROVIDERS} from ‘@angular/platform-server/testing/server’;
setBaseTestProviders(TEST_SERVER_PLATFORM_PROVIDERS,
TEST_SERVER_APPLICATION_PROVIDERS);
```
AFTER:
```
import {initTestEnvironment} from ‘@angular/core/testing’;
import {serverTestPlatform,
ServerTestModule} from ‘@angular/platform-browser-dynamic/testing’;
initTestEnvironment(
ServerTestModule,
serverTestPlatform());
```
## Bootstrap changes
```
@AppModule({
modules: [BrowserModule],
precompile: [MainComponent],
providers: […], // additional providers
directives: […], // additional platform directives
pipes: […] // additional platform pipes
})
class MyModule {
constructor(appRef: ApplicationRef) {
appRef.bootstrap(MainComponent);
}
}
// offline compile
import {browserPlatform} from ‘@angular/platform-browser’;
import {bootstrapModuleFactory} from ‘@angular/core’;
bootstrapModuleFactory(MyModuleNgFactory, browserPlatform());
// runtime compile long form
import {browserDynamicPlatform} from ‘@angular/platform-browser-dynamic’;
import {bootstrapModule} from ‘@angular/core’;
bootstrapModule(MyModule, browserDynamicPlatform());
```
Closes #9922
Part of #9726
2016-07-08 13:47:17 -04:00
/ * *
2016-08-08 20:18:50 -04:00
* Creates a factory for a platform
refactor(core): clean up platform bootstrap and initTestEnvironment
- Introduces `CompilerFactory` which can be part of a `PlatformRef`.
- Introduces `WorkerAppModule`, `WorkerUiModule`, `ServerModule`
- Introduces `serverDynamicPlatform` for applications using runtime compilation
on the server.
- Changes browser bootstrap for runtime and offline compilation (see below for an example).
* introduces `bootstrapModule` and `bootstrapModuleFactory` in `@angular/core`
* introduces new `browserDynamicPlatform` in `@angular/platform-browser-dynamic
- Changes `initTestEnvironment` (which used to be `setBaseTestProviders`) to not take a compiler factory any more (see below for an example).
BREAKING CHANGE:
## Migration from `setBaseTestProviders` to `initTestEnvironment`:
- For the browser platform:
BEFORE:
```
import {setBaseTestProviders} from ‘@angular/core/testing’;
import {TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS} from ‘@angular/platform-browser-dynamic/testing’;
setBaseTestProviders(TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS);
```
AFTER:
```
import {initTestEnvironment} from ‘@angular/core/testing’;
import {browserDynamicTestPlatform,
BrowserDynamicTestModule} from ‘@angular/platform-browser-dynamic/testing’;
initTestEnvironment(
BrowserDynamicTestModule,
browserDynamicTestPlatform());
```
- For the server platform:
BEFORE:
```
import {setBaseTestProviders} from ‘@angular/core/testing’;
import {TEST_SERVER_PLATFORM_PROVIDERS,
TEST_SERVER_APPLICATION_PROVIDERS} from ‘@angular/platform-server/testing/server’;
setBaseTestProviders(TEST_SERVER_PLATFORM_PROVIDERS,
TEST_SERVER_APPLICATION_PROVIDERS);
```
AFTER:
```
import {initTestEnvironment} from ‘@angular/core/testing’;
import {serverTestPlatform,
ServerTestModule} from ‘@angular/platform-browser-dynamic/testing’;
initTestEnvironment(
ServerTestModule,
serverTestPlatform());
```
## Bootstrap changes
```
@AppModule({
modules: [BrowserModule],
precompile: [MainComponent],
providers: […], // additional providers
directives: […], // additional platform directives
pipes: […] // additional platform pipes
})
class MyModule {
constructor(appRef: ApplicationRef) {
appRef.bootstrap(MainComponent);
}
}
// offline compile
import {browserPlatform} from ‘@angular/platform-browser’;
import {bootstrapModuleFactory} from ‘@angular/core’;
bootstrapModuleFactory(MyModuleNgFactory, browserPlatform());
// runtime compile long form
import {browserDynamicPlatform} from ‘@angular/platform-browser-dynamic’;
import {bootstrapModule} from ‘@angular/core’;
bootstrapModule(MyModule, browserDynamicPlatform());
```
Closes #9922
Part of #9726
2016-07-08 13:47:17 -04:00
*
* @experimental APIs related to application bootstrap are currently under review .
* /
2016-07-18 06:50:31 -04:00
export function createPlatformFactory (
2017-03-29 12:34:45 -04:00
parentPlatformFactory : ( ( extraProviders? : Provider [ ] ) = > PlatformRef ) | null , name : string ,
2016-08-30 21:07:40 -04:00
providers : Provider [ ] = [ ] ) : ( extraProviders? : Provider [ ] ) = > PlatformRef {
2017-01-03 19:54:46 -05:00
const marker = new InjectionToken ( ` Platform: ${ name } ` ) ;
2016-08-24 16:39:44 -04:00
return ( extraProviders : Provider [ ] = [ ] ) = > {
2017-02-12 12:16:23 -05:00
let platform = getPlatform ( ) ;
if ( ! platform || platform . injector . get ( ALLOW_MULTIPLE_PLATFORMS , false ) ) {
2016-12-16 18:21:58 -05:00
if ( parentPlatformFactory ) {
parentPlatformFactory (
2016-07-18 06:50:31 -04:00
providers . concat ( extraProviders ) . concat ( { provide : marker , useValue : true } ) ) ;
} else {
createPlatform ( ReflectiveInjector . resolveAndCreate (
providers . concat ( extraProviders ) . concat ( { provide : marker , useValue : true } ) ) ) ;
}
refactor(core): clean up platform bootstrap and initTestEnvironment
- Introduces `CompilerFactory` which can be part of a `PlatformRef`.
- Introduces `WorkerAppModule`, `WorkerUiModule`, `ServerModule`
- Introduces `serverDynamicPlatform` for applications using runtime compilation
on the server.
- Changes browser bootstrap for runtime and offline compilation (see below for an example).
* introduces `bootstrapModule` and `bootstrapModuleFactory` in `@angular/core`
* introduces new `browserDynamicPlatform` in `@angular/platform-browser-dynamic
- Changes `initTestEnvironment` (which used to be `setBaseTestProviders`) to not take a compiler factory any more (see below for an example).
BREAKING CHANGE:
## Migration from `setBaseTestProviders` to `initTestEnvironment`:
- For the browser platform:
BEFORE:
```
import {setBaseTestProviders} from ‘@angular/core/testing’;
import {TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS} from ‘@angular/platform-browser-dynamic/testing’;
setBaseTestProviders(TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS);
```
AFTER:
```
import {initTestEnvironment} from ‘@angular/core/testing’;
import {browserDynamicTestPlatform,
BrowserDynamicTestModule} from ‘@angular/platform-browser-dynamic/testing’;
initTestEnvironment(
BrowserDynamicTestModule,
browserDynamicTestPlatform());
```
- For the server platform:
BEFORE:
```
import {setBaseTestProviders} from ‘@angular/core/testing’;
import {TEST_SERVER_PLATFORM_PROVIDERS,
TEST_SERVER_APPLICATION_PROVIDERS} from ‘@angular/platform-server/testing/server’;
setBaseTestProviders(TEST_SERVER_PLATFORM_PROVIDERS,
TEST_SERVER_APPLICATION_PROVIDERS);
```
AFTER:
```
import {initTestEnvironment} from ‘@angular/core/testing’;
import {serverTestPlatform,
ServerTestModule} from ‘@angular/platform-browser-dynamic/testing’;
initTestEnvironment(
ServerTestModule,
serverTestPlatform());
```
## Bootstrap changes
```
@AppModule({
modules: [BrowserModule],
precompile: [MainComponent],
providers: […], // additional providers
directives: […], // additional platform directives
pipes: […] // additional platform pipes
})
class MyModule {
constructor(appRef: ApplicationRef) {
appRef.bootstrap(MainComponent);
}
}
// offline compile
import {browserPlatform} from ‘@angular/platform-browser’;
import {bootstrapModuleFactory} from ‘@angular/core’;
bootstrapModuleFactory(MyModuleNgFactory, browserPlatform());
// runtime compile long form
import {browserDynamicPlatform} from ‘@angular/platform-browser-dynamic’;
import {bootstrapModule} from ‘@angular/core’;
bootstrapModule(MyModule, browserDynamicPlatform());
```
Closes #9922
Part of #9726
2016-07-08 13:47:17 -04:00
}
return assertPlatform ( marker ) ;
} ;
}
2016-04-14 17:52:35 -04:00
/ * *
2017-02-12 12:16:23 -05:00
* Checks that there currently is a platform which contains the given token as a provider .
2016-06-27 15:27:23 -04:00
*
* @experimental APIs related to application bootstrap are currently under review .
2016-04-14 17:52:35 -04:00
* /
export function assertPlatform ( requiredToken : any ) : PlatformRef {
2016-09-20 17:14:57 -04:00
const platform = getPlatform ( ) ;
if ( ! platform ) {
2016-08-25 03:50:16 -04:00
throw new Error ( 'No platform exists!' ) ;
2016-04-14 17:52:35 -04:00
}
2016-09-20 17:14:57 -04:00
if ( ! platform . injector . get ( requiredToken , null ) ) {
2016-08-25 03:50:16 -04:00
throw new Error (
2016-04-14 17:52:35 -04:00
'A platform with a different configuration has been created. Please destroy it first.' ) ;
}
2016-09-20 17:14:57 -04:00
2016-04-14 17:52:35 -04:00
return platform ;
2015-11-13 14:21:16 -05:00
}
2015-11-12 16:40:29 -05:00
2016-08-02 05:32:27 -04:00
/ * *
* Destroy the existing platform .
*
* @experimental APIs related to application bootstrap are currently under review .
* /
export function destroyPlatform ( ) : void {
2016-09-20 17:14:57 -04:00
if ( _platform && ! _platform . destroyed ) {
2016-08-02 05:32:27 -04:00
_platform . destroy ( ) ;
2015-11-18 12:18:37 -05:00
}
}
2016-04-14 17:52:35 -04:00
/ * *
* Returns the current platform .
2016-06-27 15:27:23 -04:00
*
* @experimental APIs related to application bootstrap are currently under review .
2016-04-14 17:52:35 -04:00
* /
2017-03-29 12:34:45 -04:00
export function getPlatform ( ) : PlatformRef | null {
2016-09-20 17:14:57 -04:00
return _platform && ! _platform . destroyed ? _platform : null ;
2015-09-02 18:19:26 -04:00
}
/ * *
2015-09-15 18:51:15 -04: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 20:18:27 -04:00
*
2017-04-24 20:15:33 -04:00
* A page ' s platform is initialized implicitly when a platform is created via a platform factory
* ( e . g . { @link platformBrowser } ) , or explicitly by calling the { @link createPlatform } function .
2016-06-27 15:27:23 -04:00
*
2016-08-24 01:29:34 -04:00
* @stable
2015-08-20 20:18:27 -04:00
* /
2015-10-06 09:53:39 -04:00
export abstract class PlatformRef {
2015-10-26 13:50:25 -04:00
/ * *
2016-07-26 08:21:19 -04: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' ;
2016-08-15 16:44:01 -04:00
* import { platformBrowser } from '@angular/platform-browser' ;
2016-07-26 08:21:19 -04:00
*
2016-08-15 16:44:01 -04:00
* let module Ref = platformBrowser ( ) . bootstrapModuleFactory ( MyModuleNgFactory ) ;
2016-07-26 08:21:19 -04:00
* ` ` `
*
* @experimental APIs related to application bootstrap are currently under review .
* /
2017-01-26 01:32:32 -05:00
abstract bootstrapModuleFactory < M > ( module Factory : NgModuleFactory < M > ) : Promise < NgModuleRef < M > > ;
2016-07-26 08:21:19 -04:00
/ * *
* Creates an instance of an ` @NgModule ` for a given platform using the given runtime compiler .
*
* # # Simple Example
*
* ` ` ` typescript
* @NgModule ( {
* imports : [ BrowserModule ]
* } )
* class MyModule { }
*
2016-08-15 16:44:01 -04:00
* let module Ref = platformBrowser ( ) . bootstrapModule ( MyModule ) ;
2016-07-26 08:21:19 -04:00
* ` ` `
* @stable
2015-10-26 13:50:25 -04:00
* /
2017-01-26 01:36:38 -05:00
abstract bootstrapModule < M > (
module Type : Type < M > ,
compilerOptions? : CompilerOptions | CompilerOptions [ ] ) : Promise < NgModuleRef < M > > ;
2016-07-26 08:21:19 -04:00
2016-08-02 05:32:27 -04:00
/ * *
* Register a listener to be called when the platform is disposed .
* /
abstract onDestroy ( callback : ( ) = > void ) : void ;
2015-09-02 18:19:26 -04:00
/ * *
2015-09-15 18:51:15 -04:00
* Retrieve the platform { @link Injector } , which is the parent injector for
2015-10-11 01:11:13 -04:00
* every Angular application on the page and provides singleton providers .
2015-09-02 18:19:26 -04:00
* /
2017-01-26 01:32:32 -05:00
abstract get injector ( ) : Injector ;
2015-08-20 20:18:27 -04:00
2016-08-02 05:32:27 -04:00
/ * *
* Destroy the Angular platform and all Angular applications on the page .
* /
abstract destroy ( ) : void ;
2017-01-26 01:32:32 -05:00
abstract get destroyed ( ) : boolean ;
2015-10-06 09:53:39 -04:00
}
2016-08-30 21:07:40 -04:00
function _callAndReportToErrorHandler ( errorHandler : ErrorHandler , callback : ( ) = > any ) : any {
2016-07-29 09:47:40 -04:00
try {
const result = callback ( ) ;
if ( isPromise ( result ) ) {
return result . catch ( ( e : any ) = > {
2016-08-25 03:50:16 -04:00
errorHandler . handleError ( e ) ;
2016-07-29 09:47:40 -04:00
// rethrow as the exception handler might not do it
throw e ;
} ) ;
}
2016-09-20 17:14:57 -04:00
return result ;
2016-07-29 09:47:40 -04:00
} catch ( e ) {
2016-08-25 03:50:16 -04:00
errorHandler . handleError ( e ) ;
2016-07-29 09:47:40 -04:00
// rethrow as the exception handler might not do it
throw e ;
}
}
2017-01-30 19:25:15 -05:00
/ * *
* workaround https : //github.com/angular/tsickle/issues/350
* @suppress { checkTypes }
* /
2016-04-14 17:52:35 -04:00
@Injectable ( )
2015-10-06 09:53:39 -04:00
export class PlatformRef_ extends PlatformRef {
2016-08-02 05:32:27 -04:00
private _modules : NgModuleRef < any > [ ] = [ ] ;
private _destroyListeners : Function [ ] = [ ] ;
private _destroyed : boolean = false ;
2015-10-06 09:53:39 -04:00
2016-07-29 09:47:40 -04:00
constructor ( private _injector : Injector ) { super ( ) ; }
2015-10-06 09:53:39 -04:00
2016-08-02 05:32:27 -04:00
onDestroy ( callback : ( ) = > void ) : void { this . _destroyListeners . push ( callback ) ; }
2015-09-02 18:19:26 -04:00
2016-04-14 17:52:35 -04:00
get injector ( ) : Injector { return this . _injector ; }
2015-09-02 18:19:26 -04:00
2016-08-02 05:32:27 -04:00
get destroyed() { return this . _destroyed ; }
2016-04-14 17:52:35 -04:00
2016-08-02 05:32:27 -04:00
destroy() {
if ( this . _destroyed ) {
2016-08-25 03:50:16 -04:00
throw new Error ( 'The platform has already been destroyed!' ) ;
2016-08-02 05:32:27 -04:00
}
2016-09-20 17:14:57 -04:00
this . _modules . slice ( ) . forEach ( module = > module .destroy ( ) ) ;
this . _destroyListeners . forEach ( listener = > listener ( ) ) ;
2016-08-02 05:32:27 -04:00
this . _destroyed = true ;
2015-09-02 18:19:26 -04:00
}
2016-07-29 09:47:40 -04:00
bootstrapModuleFactory < M > ( module Factory : NgModuleFactory < M > ) : Promise < NgModuleRef < M > > {
2017-03-29 12:34:45 -04:00
return this . _bootstrapModuleFactoryWithZone ( module Factory ) ;
2016-08-05 16:32:04 -04:00
}
2017-03-29 12:34:45 -04:00
private _bootstrapModuleFactoryWithZone < M > ( module Factory : NgModuleFactory < M > , ngZone? : NgZone ) :
2016-08-05 16:32:04 -04:00
Promise < NgModuleRef < M > > {
2016-07-26 08:21:19 -04: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 16:32:04 -04:00
if ( ! ngZone ) ngZone = new NgZone ( { enableLongStackTrace : isDevMode ( ) } ) ;
2016-07-29 09:47:40 -04: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 ) ;
2017-05-11 13:26:02 -04:00
const module Ref = < InternalNgModuleRef < M > > module Factory.create ( ngZoneInjector ) ;
2016-08-25 03:50:16 -04:00
const exceptionHandler : ErrorHandler = module Ref.injector.get ( ErrorHandler , null ) ;
2016-07-29 17:45:05 -04:00
if ( ! exceptionHandler ) {
2016-08-30 21:07:40 -04:00
throw new Error ( 'No ErrorHandler. Is platform module (BrowserModule) included?' ) ;
2016-07-29 17:45:05 -04:00
}
2017-03-01 17:10:59 -05:00
module Ref.onDestroy ( ( ) = > remove ( this . _modules , module Ref ) ) ;
2017-03-29 12:34:45 -04:00
ngZone ! . onError . subscribe ( { next : ( error : any ) = > { exceptionHandler . handleError ( error ) ; } } ) ;
2016-08-30 21:07:40 -04:00
return _callAndReportToErrorHandler ( exceptionHandler , ( ) = > {
2016-08-02 10:54:14 -04:00
const initStatus : ApplicationInitStatus = module Ref.injector.get ( ApplicationInitStatus ) ;
2016-08-02 10:38:14 -04:00
return initStatus . donePromise . then ( ( ) = > {
2016-08-02 09:54:08 -04:00
this . _moduleDoBootstrap ( module Ref ) ;
2016-07-29 09:47:40 -04:00
return module Ref ;
} ) ;
} ) ;
} ) ;
2016-07-26 08:21:19 -04:00
}
2016-08-10 21:21:28 -04:00
bootstrapModule < M > ( module Type : Type < M > , compilerOptions : CompilerOptions | CompilerOptions [ ] = [ ] ) :
Promise < NgModuleRef < M > > {
2017-03-29 12:34:45 -04:00
return this . _bootstrapModuleWithZone ( module Type , compilerOptions ) ;
2016-08-05 16:32:04 -04:00
}
private _bootstrapModuleWithZone < M > (
2017-01-19 06:04:24 -05:00
module Type : Type < M > , compilerOptions : CompilerOptions | CompilerOptions [ ] = [ ] ,
2017-03-29 12:34:45 -04:00
ngZone? : NgZone ) : Promise < NgModuleRef < M > > {
2016-07-26 08:21:19 -04:00
const compilerFactory : CompilerFactory = this . injector . get ( CompilerFactory ) ;
const compiler = compilerFactory . createCompiler (
2016-09-20 17:14:57 -04:00
Array . isArray ( compilerOptions ) ? compilerOptions : [ compilerOptions ] ) ;
2016-08-19 16:51:45 -04:00
2016-07-26 08:21:19 -04:00
return compiler . compileModuleAsync ( module Type )
2016-08-05 16:32:04 -04:00
. then ( ( module Factory ) = > this . _bootstrapModuleFactoryWithZone ( module Factory , ngZone ) ) ;
2016-07-26 08:21:19 -04:00
}
2016-08-02 09:54:08 -04:00
2017-05-11 13:26:02 -04:00
private _moduleDoBootstrap ( module Ref : InternalNgModuleRef < any > ) : void {
const appRef = module Ref.injector.get ( ApplicationRef ) as ApplicationRef ;
if ( module Ref._bootstrapComponents.length > 0 ) {
module Ref._bootstrapComponents.forEach ( f = > appRef . bootstrap ( f ) ) ;
2016-08-02 09:54:08 -04:00
} else if ( module Ref.instance.ngDoBootstrap ) {
module Ref.instance.ngDoBootstrap ( appRef ) ;
} else {
2016-08-25 03:50:16 -04:00
throw new Error (
2016-08-02 09:54:08 -04:00
` The module ${ stringify ( module Ref.instance.constructor ) } was bootstrapped, but it does not declare "@NgModule.bootstrap" components nor a "ngDoBootstrap" method. ` +
` Please define one of these. ` ) ;
}
2017-01-01 12:46:53 -05:00
this . _modules . push ( module Ref ) ;
2016-08-02 09:54:08 -04:00
}
2015-09-02 18:19:26 -04:00
}
/ * *
2015-09-15 18:51:15 -04:00
* A reference to an Angular application running on a page .
2015-09-02 18:19:26 -04:00
*
2016-08-24 01:29:34 -04:00
* @stable
2015-09-02 18:19:26 -04:00
* /
2015-10-06 09:53:39 -04:00
export abstract class ApplicationRef {
2015-08-20 20:18:27 -04:00
/ * *
2015-09-15 18:51:15 -04:00
* Bootstrap a new component at the root level of the application .
*
2015-11-17 12:41:31 -05:00
* # # # Bootstrap process
2015-09-15 18:51:15 -04: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 .
*
2017-03-31 10:37:20 -04:00
* Optionally , a component can be mounted onto a DOM element that does not match the
* [ componentType ] ' s selector .
*
2015-10-19 10:37:32 -04:00
* # # # Example
2015-11-30 11:28:54 -05:00
* { @example core / ts / platform / platform . ts region = 'longform' }
2015-09-02 18:19:26 -04:00
* /
2017-03-31 10:37:20 -04:00
abstract bootstrap < C > (
componentFactory : ComponentFactory < C > | Type < C > ,
rootSelectorOrNode? : string | any ) : ComponentRef < C > ;
2015-10-06 09:53:39 -04:00
2015-10-28 13:34:13 -04: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 19:22:07 -04:00
/ * *
* Get a list of component types registered to this application .
2016-08-02 10:49:33 -04:00
* This list is populated even before the component is created .
2015-10-09 19:22:07 -04:00
* /
2017-01-26 01:32:32 -05:00
abstract get componentTypes ( ) : Type < any > [ ] ;
2016-08-02 10:49:33 -04:00
2016-08-02 09:54:08 -04:00
/ * *
* Get a list of components registered to this application .
* /
2017-01-26 01:32:32 -05:00
abstract get components ( ) : ComponentRef < any > [ ] ;
2016-11-04 14:58:06 -04:00
/ * *
* Attaches a view so that it will be dirty checked .
* The view will be automatically detached when it is destroyed .
* This will throw if the view is already attached to a ViewContainer .
* /
2017-01-26 01:32:32 -05:00
abstract attachView ( view : ViewRef ) : void ;
2016-11-04 14:58:06 -04:00
/ * *
* Detaches a view from dirty checking again .
* /
2017-01-26 01:32:32 -05:00
abstract detachView ( view : ViewRef ) : void ;
2016-11-04 14:58:06 -04:00
/ * *
* Returns the number of attached views .
* /
2017-01-26 01:32:32 -05:00
abstract get viewCount ( ) : number ;
2017-02-03 08:42:22 -05:00
/ * *
* Returns an Observable that indicates when the application is stable or unstable .
* /
abstract get isStable ( ) : Observable < boolean > ;
2015-10-06 09:53:39 -04:00
}
2017-01-30 19:25:15 -05:00
/ * *
* workaround https : //github.com/angular/tsickle/issues/350
* @suppress { checkTypes }
* /
2016-04-14 17:52:35 -04:00
@Injectable ( )
2015-10-06 09:53:39 -04:00
export class ApplicationRef_ extends ApplicationRef {
2015-10-28 13:34:13 -04:00
/** @internal */
static _tickScope : WtfScopeFn = wtfCreateScope ( 'ApplicationRef#tick()' ) ;
2017-01-03 19:54:46 -05:00
private _bootstrapListeners : ( ( compRef : ComponentRef < any > ) = > void ) [ ] = [ ] ;
2016-04-30 13:52:04 -04:00
private _rootComponents : ComponentRef < any > [ ] = [ ] ;
2016-08-10 21:21:28 -04:00
private _rootComponentTypes : Type < any > [ ] = [ ] ;
2017-02-17 11:56:49 -05:00
private _views : InternalViewRef [ ] = [ ] ;
2015-10-28 13:34:13 -04:00
private _runningTick : boolean = false ;
private _enforceNoNewChanges : boolean = false ;
2017-02-03 08:42:22 -05:00
private _isStable : Observable < boolean > ;
private _stable = true ;
2015-10-06 09:53:39 -04:00
feat(browser): use AppModules for bootstrap in the browser
This introduces the `BrowserModule` to be used for long form
bootstrap and offline compile bootstrap:
```
@AppModule({
modules: [BrowserModule],
precompile: [MainComponent],
providers: […], // additional providers
directives: […], // additional platform directives
pipes: […] // additional platform pipes
})
class MyModule {
constructor(appRef: ApplicationRef) {
appRef.bootstrap(MainComponent);
}
}
// offline compile
import {bootstrapModuleFactory} from ‘@angular/platform-browser’;
bootstrapModuleFactory(MyModuleNgFactory);
// runtime compile long form
import {bootstrapModule} from ‘@angular/platform-browser-dynamic’;
bootstrapModule(MyModule);
```
The short form, `bootstrap(...)`, can now creates a module on the fly,
given `directives`, `pipes, `providers`, `precompile` and `modules`
properties.
Related changes:
- make `SanitizationService`, `SecurityContext` public in `@angular/core` so that the offline compiler can resolve the token
- move `AnimationDriver` to `platform-browser` and make it
public so that the offline compiler can resolve the token
BREAKING CHANGES:
- short form bootstrap does no longer allow
to inject compiler internals (i.e. everything
from `@angular/compiler). Inject `Compiler` instead.
To provide custom providers for the compiler,
create a custom compiler via `browserCompiler({providers: [...]})`
and pass that into the `bootstrap` method.
2016-06-30 16:07:17 -04:00
constructor (
2016-08-02 05:32:27 -04:00
private _zone : NgZone , private _console : Console , private _injector : Injector ,
2016-08-25 03:50:16 -04:00
private _exceptionHandler : ErrorHandler ,
feat(browser): use AppModules for bootstrap in the browser
This introduces the `BrowserModule` to be used for long form
bootstrap and offline compile bootstrap:
```
@AppModule({
modules: [BrowserModule],
precompile: [MainComponent],
providers: […], // additional providers
directives: […], // additional platform directives
pipes: […] // additional platform pipes
})
class MyModule {
constructor(appRef: ApplicationRef) {
appRef.bootstrap(MainComponent);
}
}
// offline compile
import {bootstrapModuleFactory} from ‘@angular/platform-browser’;
bootstrapModuleFactory(MyModuleNgFactory);
// runtime compile long form
import {bootstrapModule} from ‘@angular/platform-browser-dynamic’;
bootstrapModule(MyModule);
```
The short form, `bootstrap(...)`, can now creates a module on the fly,
given `directives`, `pipes, `providers`, `precompile` and `modules`
properties.
Related changes:
- make `SanitizationService`, `SecurityContext` public in `@angular/core` so that the offline compiler can resolve the token
- move `AnimationDriver` to `platform-browser` and make it
public so that the offline compiler can resolve the token
BREAKING CHANGES:
- short form bootstrap does no longer allow
to inject compiler internals (i.e. everything
from `@angular/compiler). Inject `Compiler` instead.
To provide custom providers for the compiler,
create a custom compiler via `browserCompiler({providers: [...]})`
and pass that into the `bootstrap` method.
2016-06-30 16:07:17 -04:00
private _componentFactoryResolver : ComponentFactoryResolver ,
2017-03-01 14:16:56 -05:00
private _initStatus : ApplicationInitStatus ) {
2015-10-06 09:53:39 -04:00
super ( ) ;
2016-06-17 17:09:19 -04:00
this . _enforceNoNewChanges = isDevMode ( ) ;
2016-08-02 18:53:34 -04:00
this . _zone . onMicrotaskEmpty . subscribe (
{ next : ( ) = > { this . _zone . run ( ( ) = > { this . tick ( ) ; } ) ; } } ) ;
2017-02-03 08:42:22 -05:00
const isCurrentlyStable = new Observable < boolean > ( ( observer : Observer < boolean > ) = > {
this . _stable = this . _zone . isStable && ! this . _zone . hasPendingMacrotasks &&
! this . _zone . hasPendingMicrotasks ;
this . _zone . runOutsideAngular ( ( ) = > {
observer . next ( this . _stable ) ;
observer . complete ( ) ;
} ) ;
} ) ;
const isStable = new Observable < boolean > ( ( observer : Observer < boolean > ) = > {
const stableSub : Subscription = this . _zone . onStable . subscribe ( ( ) = > {
NgZone . assertNotInAngularZone ( ) ;
// Check whether there are no pending macro/micro tasks in the next tick
// to allow for NgZone to update the state.
scheduleMicroTask ( ( ) = > {
if ( ! this . _stable && ! this . _zone . hasPendingMacrotasks &&
! this . _zone . hasPendingMicrotasks ) {
this . _stable = true ;
observer . next ( true ) ;
}
} ) ;
} ) ;
const unstableSub : Subscription = this . _zone . onUnstable . subscribe ( ( ) = > {
NgZone . assertInAngularZone ( ) ;
if ( this . _stable ) {
this . _stable = false ;
this . _zone . runOutsideAngular ( ( ) = > { observer . next ( false ) ; } ) ;
}
} ) ;
return ( ) = > {
stableSub . unsubscribe ( ) ;
unstableSub . unsubscribe ( ) ;
} ;
} ) ;
this . _isStable = merge ( isCurrentlyStable , share . call ( isStable ) ) ;
2015-10-06 09:53:39 -04:00
}
2016-11-04 14:58:06 -04:00
attachView ( viewRef : ViewRef ) : void {
2017-02-17 11:56:49 -05:00
const view = ( viewRef as InternalViewRef ) ;
2016-11-04 14:58:06 -04:00
this . _views . push ( view ) ;
view . attachToAppRef ( this ) ;
2015-10-28 13:34:13 -04:00
}
2016-11-04 14:58:06 -04:00
detachView ( viewRef : ViewRef ) : void {
2017-02-17 11:56:49 -05:00
const view = ( viewRef as InternalViewRef ) ;
2017-03-01 17:10:59 -05:00
remove ( this . _views , view ) ;
2017-02-22 13:05:56 -05:00
view . detachFromAppRef ( ) ;
2015-11-10 13:40:33 -05:00
}
2017-03-31 10:37:20 -04:00
bootstrap < C > ( componentOrFactory : ComponentFactory < C > | Type < C > , rootSelectorOrNode? : string | any ) :
ComponentRef < C > {
2016-08-02 10:38:14 -04:00
if ( ! this . _initStatus . done ) {
2016-08-25 03:50:16 -04:00
throw new Error (
2016-08-02 10:38:14 -04:00
'Cannot bootstrap as there are still asynchronous initializers running. Bootstrap components in the `ngDoBootstrap` method of the root module.' ) ;
}
2016-08-02 10:48:15 -04:00
let componentFactory : ComponentFactory < C > ;
if ( componentOrFactory instanceof ComponentFactory ) {
componentFactory = componentOrFactory ;
} else {
2017-03-29 12:34:45 -04:00
componentFactory =
this . _componentFactoryResolver . resolveComponentFactory ( componentOrFactory ) ! ;
2016-08-02 10:48:15 -04:00
}
this . _rootComponentTypes . push ( componentFactory . componentType ) ;
2017-03-14 19:26:17 -04:00
// Create a factory associated with the current module if it's not bound to some other
const ngModule = componentFactory instanceof ComponentFactoryBoundToModule ?
null :
this . _injector . get ( NgModuleRef ) ;
2017-03-31 10:37:20 -04:00
const selectorOrNode = rootSelectorOrNode || componentFactory . selector ;
const compRef = componentFactory . create ( Injector . NULL , [ ] , selectorOrNode , ngModule ) ;
2017-03-14 19:26:17 -04:00
2016-08-02 10:48:15 -04:00
compRef . onDestroy ( ( ) = > { this . _unloadComponent ( compRef ) ; } ) ;
2016-09-20 17:14:57 -04:00
const testability = compRef . injector . get ( Testability , null ) ;
if ( testability ) {
2016-08-02 10:48:15 -04:00
compRef . injector . get ( TestabilityRegistry )
. registerApplication ( compRef . location . nativeElement , testability ) ;
}
2016-04-14 17:52:35 -04:00
2016-08-02 10:48:15 -04:00
this . _loadComponent ( compRef ) ;
if ( isDevMode ( ) ) {
this . _console . log (
2017-01-03 13:03:58 -05:00
` Angular is running in the development mode. Call enableProdMode() to enable the production mode. ` ) ;
2016-08-02 10:48:15 -04:00
}
return compRef ;
2015-09-02 18:19:26 -04:00
}
2016-11-04 14:58:06 -04:00
private _loadComponent ( componentRef : ComponentRef < any > ) : void {
this . attachView ( componentRef . hostView ) ;
2015-11-10 13:40:33 -05:00
this . tick ( ) ;
2016-02-11 20:01:17 -05:00
this . _rootComponents . push ( componentRef ) ;
2016-08-02 08:22:44 -04:00
// Get the listeners lazily to prevent DI cycles.
const listeners =
2017-01-03 19:54:46 -05:00
this . _injector . get ( APP_BOOTSTRAP_LISTENER , [ ] ) . concat ( this . _bootstrapListeners ) ;
2016-08-02 08:22:44 -04:00
listeners . forEach ( ( listener ) = > listener ( componentRef ) ) ;
2015-11-10 13:40:33 -05:00
}
2016-11-04 14:58:06 -04:00
private _unloadComponent ( componentRef : ComponentRef < any > ) : void {
this . detachView ( componentRef . hostView ) ;
2017-03-01 17:10:59 -05:00
remove ( this . _rootComponents , componentRef ) ;
2015-11-10 13:40:33 -05:00
}
2015-10-28 13:34:13 -04:00
tick ( ) : void {
if ( this . _runningTick ) {
2016-08-25 03:50:16 -04:00
throw new Error ( 'ApplicationRef.tick is called recursively' ) ;
2015-10-28 13:34:13 -04:00
}
2016-09-20 17:14:57 -04:00
const scope = ApplicationRef_ . _tickScope ( ) ;
2015-10-28 13:34:13 -04:00
try {
this . _runningTick = true ;
2017-02-17 11:56:49 -05:00
this . _views . forEach ( ( view ) = > view . detectChanges ( ) ) ;
2015-10-28 13:34:13 -04:00
if ( this . _enforceNoNewChanges ) {
2017-02-17 11:56:49 -05:00
this . _views . forEach ( ( view ) = > view . checkNoChanges ( ) ) ;
2015-10-28 13:34:13 -04:00
}
2017-04-28 14:50:45 -04:00
} catch ( e ) {
// Attention: Don't rethrow as it could cancel subscriptions to Observables!
this . _exceptionHandler . handleError ( e ) ;
2015-10-28 13:34:13 -04:00
} finally {
this . _runningTick = false ;
2016-09-20 17:14:57 -04:00
wtfLeave ( scope ) ;
2015-10-28 13:34:13 -04:00
}
}
2016-08-02 05:32:27 -04:00
ngOnDestroy() {
2015-09-02 18:19:26 -04:00
// TODO(alxhub): Dispose of the NgZone.
2016-11-04 14:58:06 -04:00
this . _views . slice ( ) . forEach ( ( view ) = > view . destroy ( ) ) ;
2015-09-02 18:19:26 -04:00
}
2015-10-09 19:22:07 -04:00
2016-11-04 14:58:06 -04:00
get viewCount() { return this . _views . length ; }
2016-08-10 21:21:28 -04:00
get componentTypes ( ) : Type < any > [ ] { return this . _rootComponentTypes ; }
2016-08-02 09:54:08 -04:00
get components ( ) : ComponentRef < any > [ ] { return this . _rootComponents ; }
2017-02-03 08:42:22 -05:00
get isStable ( ) : Observable < boolean > { return this . _isStable ; }
2015-08-20 20:18:27 -04:00
}
2017-03-01 17:10:59 -05:00
function remove < T > ( list : T [ ] , el : T ) : void {
const index = list . indexOf ( el ) ;
if ( index > - 1 ) {
list . splice ( index , 1 ) ;
}
}