diff --git a/modules/angular2/src/core/application.js b/modules/angular2/src/core/application.js index 7ff2cb3b66..4dd015248b 100644 --- a/modules/angular2/src/core/application.js +++ b/modules/angular2/src/core/application.js @@ -78,7 +78,7 @@ function _injectorBindings(appComponentType) { [appViewToken]), bind(appComponentType).toFactory((rootView) => rootView.elementInjectors[0].getComponent(), [appViewToken]), - bind(LifeCycle).toFactory((cd) => new LifeCycle(cd, assertionsEnabled()), [appChangeDetectorToken]) + bind(LifeCycle).toFactory(() => new LifeCycle(null, assertionsEnabled()),[]) ]; } @@ -108,9 +108,11 @@ export function bootstrap(appComponentType: Type, bindings=null, givenBootstrapE var appInjector = _createAppInjector(appComponentType, bindings); - PromiseWrapper.then(appInjector.asyncGet(LifeCycle), - (lc) => { - lc.registerWith(zone); + PromiseWrapper.then(appInjector.asyncGet(appViewToken), + (rootView) => { + // retrieve life cycle: may have already been created if injected in root component + var lc=appInjector.get(LifeCycle); + lc.registerWith(zone, rootView.changeDetector); lc.tick(); //the first tick that will bootstrap the app bootstrapProcess.complete(appInjector); diff --git a/modules/angular2/src/core/life_cycle/life_cycle.js b/modules/angular2/src/core/life_cycle/life_cycle.js index a7c2483408..23d6a32f19 100644 --- a/modules/angular2/src/core/life_cycle/life_cycle.js +++ b/modules/angular2/src/core/life_cycle/life_cycle.js @@ -2,17 +2,18 @@ import {FIELD, print} from 'angular2/src/facade/lang'; import {ChangeDetector} from 'angular2/change_detection'; import {VmTurnZone} from 'angular2/src/core/zone/vm_turn_zone'; import {ListWrapper} from 'angular2/src/facade/collection'; +import {isPresent} from 'angular2/src/facade/lang'; export class LifeCycle { _changeDetector:ChangeDetector; _enforceNoNewChanges:boolean; - constructor(changeDetector:ChangeDetector, enforceNoNewChanges:boolean = false) { - this._changeDetector = changeDetector; + constructor(changeDetector:ChangeDetector = null, enforceNoNewChanges:boolean = false) { + this._changeDetector = changeDetector; // may be null when instantiated from application bootstrap this._enforceNoNewChanges = enforceNoNewChanges; } - registerWith(zone:VmTurnZone) { + registerWith(zone:VmTurnZone, changeDetector:ChangeDetector = null) { // temporary error handler, we should inject one var errorHandler = (exception, stackTrace) => { var longStackTrace = ListWrapper.join(stackTrace, "\n\n-----async gap-----\n"); @@ -20,6 +21,10 @@ export class LifeCycle { throw exception; }; + if (isPresent(changeDetector)) { + this._changeDetector=changeDetector; + } + zone.initCallbacks({ onErrorHandler: errorHandler, onTurnDone: () => this.tick() @@ -32,4 +37,4 @@ export class LifeCycle { this._changeDetector.checkNoChanges(); } } -} \ No newline at end of file +} diff --git a/modules/angular2/test/core/application_spec.js b/modules/angular2/test/core/application_spec.js index d59340bb36..a8da189bae 100644 --- a/modules/angular2/test/core/application_spec.js +++ b/modules/angular2/test/core/application_spec.js @@ -7,6 +7,7 @@ import {ListWrapper} from 'angular2/src/facade/collection'; import {PromiseWrapper} from 'angular2/src/facade/async'; import {bind, Inject} from 'angular2/di'; import {TemplateConfig} from 'angular2/src/core/annotations/template_config'; +import {LifeCycle} from 'angular2/src/core/life_cycle/life_cycle'; @Component({ selector: 'hello-app', @@ -51,6 +52,21 @@ class HelloRootCmp3 { } } +@Component({ + selector: 'hello-app', + template: new TemplateConfig({ + inline: '', + directives: [] + }) +}) +class HelloRootCmp4 { + lc; + + constructor(@Inject(LifeCycle) lc) { + this.lc = lc; + } +} + export function main() { var fakeDoc, el, el2, testBindings; @@ -126,5 +142,14 @@ export function main() { done(); }); }); + + it("should avoid cyclic dependencies when root component requires Lifecycle through DI", (done) => { + var injectorPromise = bootstrap(HelloRootCmp4, testBindings); + + injectorPromise.then((injector) => { + expect(injector.get(HelloRootCmp4).lc).toBe(injector.get(LifeCycle)); + done(); + }); + }); }); }