@@ -22,7 +22,6 @@ import {
2222} from 'angular2/src/core/facade/exceptions' ;
2323import { DOM } from 'angular2/src/core/dom/dom_adapter' ;
2424import { internalView } from 'angular2/src/core/linker/view_ref' ;
25- import { LifeCycle , LifeCycle_ } from 'angular2/src/core/life_cycle/life_cycle' ;
2625import {
2726 IterableDiffers ,
2827 defaultIterableDiffers ,
@@ -42,6 +41,8 @@ import {Compiler} from 'angular2/src/core/linker/compiler';
4241import { DynamicComponentLoader_ } from "./linker/dynamic_component_loader" ;
4342import { AppViewManager_ } from "./linker/view_manager" ;
4443import { Compiler_ } from "./linker/compiler" ;
44+ import { wtfLeave , wtfCreateScope , WtfScopeFn } from './profile/profile' ;
45+ import { ChangeDetectorRef } from 'angular2/src/core/change_detection/change_detector_ref' ;
4546
4647/**
4748 * Constructs the set of providers meant for use at the platform level.
@@ -103,12 +104,7 @@ export function applicationCommonProviders(): Array<Type | Provider | any[]> {
103104 provide ( KeyValueDiffers , { useValue : defaultKeyValueDiffers } ) ,
104105 DirectiveResolver ,
105106 PipeResolver ,
106- provide ( DynamicComponentLoader , { useClass : DynamicComponentLoader_ } ) ,
107- provide ( LifeCycle ,
108- {
109- useFactory : ( exceptionHandler ) => new LifeCycle_ ( null , assertionsEnabled ( ) ) ,
110- deps : [ ExceptionHandler ]
111- } )
107+ provide ( DynamicComponentLoader , { useClass : DynamicComponentLoader_ } )
112108 ] ;
113109}
114110
@@ -333,20 +329,49 @@ export abstract class ApplicationRef {
333329 */
334330 abstract dispose ( ) : void ;
335331
332+ /**
333+ * Invoke this method to explicitly process change detection and its side-effects.
334+ *
335+ * In development mode, `tick()` also performs a second change detection cycle to ensure that no
336+ * further changes are detected. If additional changes are picked up during this second cycle,
337+ * bindings in the app have side-effects that cannot be resolved in a single change detection
338+ * pass.
339+ * In this case, Angular throws an error, since an Angular application can only have one change
340+ * detection pass during which all change detection must complete.
341+ */
342+ abstract tick ( ) : void ;
343+
336344 /**
337345 * Get a list of component types registered to this application.
338346 */
339347 get componentTypes ( ) : Type [ ] { return unimplemented ( ) ; } ;
340348}
341349
342350export class ApplicationRef_ extends ApplicationRef {
351+ /** @internal */
352+ static _tickScope : WtfScopeFn = wtfCreateScope ( 'ApplicationRef#tick()' ) ;
353+
354+ /** @internal */
343355 private _bootstrapListeners : Function [ ] = [ ] ;
356+ /** @internal */
344357 private _disposeListeners : Function [ ] = [ ] ;
358+ /** @internal */
345359 private _rootComponents : ComponentRef [ ] = [ ] ;
360+ /** @internal */
346361 private _rootComponentTypes : Type [ ] = [ ] ;
362+ /** @internal */
363+ private _changeDetectorRefs : ChangeDetectorRef [ ] = [ ] ;
364+ /** @internal */
365+ private _runningTick : boolean = false ;
366+ /** @internal */
367+ private _enforceNoNewChanges : boolean = false ;
347368
348369 constructor ( private _platform : PlatformRef_ , private _zone : NgZone , private _injector : Injector ) {
349370 super ( ) ;
371+ if ( isPresent ( this . _zone ) ) {
372+ this . _zone . overrideOnTurnDone ( ( ) => this . tick ( ) ) ;
373+ }
374+ this . _enforceNoNewChanges = assertionsEnabled ( ) ;
350375 }
351376
352377 registerBootstrapListener ( listener : ( ref : ComponentRef ) => void ) : void {
@@ -355,6 +380,10 @@ export class ApplicationRef_ extends ApplicationRef {
355380
356381 registerDisposeListener ( dispose : ( ) => void ) : void { this . _disposeListeners . push ( dispose ) ; }
357382
383+ registerChangeDetector ( changeDetector : ChangeDetectorRef ) : void {
384+ this . _changeDetectorRefs . push ( changeDetector ) ;
385+ }
386+
358387 bootstrap ( componentType : Type ,
359388 providers ?: Array < Type | Provider | any [ ] > ) : Promise < ComponentRef > {
360389 var completer = PromiseWrapper . completer ( ) ;
@@ -370,9 +399,8 @@ export class ApplicationRef_ extends ApplicationRef {
370399 var compRefToken : Promise < ComponentRef > = injector . get ( APP_COMPONENT_REF_PROMISE ) ;
371400 var tick = ( componentRef ) => {
372401 var appChangeDetector = internalView ( componentRef . hostView ) . changeDetector ;
373- var lc = injector . get ( LifeCycle ) ;
374- lc . registerWith ( this . _zone , appChangeDetector ) ;
375- lc . tick ( ) ;
402+ this . _changeDetectorRefs . push ( appChangeDetector . ref ) ;
403+ this . tick ( ) ;
376404 completer . resolve ( componentRef ) ;
377405 this . _rootComponents . push ( componentRef ) ;
378406 this . _bootstrapListeners . forEach ( ( listener ) => listener ( componentRef ) ) ;
@@ -395,6 +423,24 @@ export class ApplicationRef_ extends ApplicationRef {
395423
396424 get zone ( ) : NgZone { return this . _zone ; }
397425
426+ tick ( ) : void {
427+ if ( this . _runningTick ) {
428+ throw new BaseException ( "ApplicationRef.tick is called recursively" ) ;
429+ }
430+
431+ var s = ApplicationRef_ . _tickScope ( ) ;
432+ try {
433+ this . _runningTick = true ;
434+ this . _changeDetectorRefs . forEach ( ( detector ) => detector . detectChanges ( ) ) ;
435+ if ( this . _enforceNoNewChanges ) {
436+ this . _changeDetectorRefs . forEach ( ( detector ) => detector . checkNoChanges ( ) ) ;
437+ }
438+ } finally {
439+ this . _runningTick = false ;
440+ wtfLeave ( s ) ;
441+ }
442+ }
443+
398444 dispose ( ) : void {
399445 // TODO(alxhub): Dispose of the NgZone.
400446 this . _rootComponents . forEach ( ( ref ) => ref . dispose ( ) ) ;
0 commit comments