fix(life_cycle): remove cyclic dependency

fixes #477

Closes #530
This commit is contained in:
Bertrand Laporte 2015-02-03 17:05:29 -08:00 committed by Misko Hevery
parent 5010cf9757
commit 63f23ec0b6
3 changed files with 40 additions and 8 deletions

View File

@ -78,7 +78,7 @@ function _injectorBindings(appComponentType) {
[appViewToken]), [appViewToken]),
bind(appComponentType).toFactory((rootView) => rootView.elementInjectors[0].getComponent(), bind(appComponentType).toFactory((rootView) => rootView.elementInjectors[0].getComponent(),
[appViewToken]), [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); var appInjector = _createAppInjector(appComponentType, bindings);
PromiseWrapper.then(appInjector.asyncGet(LifeCycle), PromiseWrapper.then(appInjector.asyncGet(appViewToken),
(lc) => { (rootView) => {
lc.registerWith(zone); // 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 lc.tick(); //the first tick that will bootstrap the app
bootstrapProcess.complete(appInjector); bootstrapProcess.complete(appInjector);

View File

@ -2,17 +2,18 @@ import {FIELD, print} from 'angular2/src/facade/lang';
import {ChangeDetector} from 'angular2/change_detection'; import {ChangeDetector} from 'angular2/change_detection';
import {VmTurnZone} from 'angular2/src/core/zone/vm_turn_zone'; import {VmTurnZone} from 'angular2/src/core/zone/vm_turn_zone';
import {ListWrapper} from 'angular2/src/facade/collection'; import {ListWrapper} from 'angular2/src/facade/collection';
import {isPresent} from 'angular2/src/facade/lang';
export class LifeCycle { export class LifeCycle {
_changeDetector:ChangeDetector; _changeDetector:ChangeDetector;
_enforceNoNewChanges:boolean; _enforceNoNewChanges:boolean;
constructor(changeDetector:ChangeDetector, enforceNoNewChanges:boolean = false) { constructor(changeDetector:ChangeDetector = null, enforceNoNewChanges:boolean = false) {
this._changeDetector = changeDetector; this._changeDetector = changeDetector; // may be null when instantiated from application bootstrap
this._enforceNoNewChanges = enforceNoNewChanges; this._enforceNoNewChanges = enforceNoNewChanges;
} }
registerWith(zone:VmTurnZone) { registerWith(zone:VmTurnZone, changeDetector:ChangeDetector = null) {
// temporary error handler, we should inject one // temporary error handler, we should inject one
var errorHandler = (exception, stackTrace) => { var errorHandler = (exception, stackTrace) => {
var longStackTrace = ListWrapper.join(stackTrace, "\n\n-----async gap-----\n"); var longStackTrace = ListWrapper.join(stackTrace, "\n\n-----async gap-----\n");
@ -20,6 +21,10 @@ export class LifeCycle {
throw exception; throw exception;
}; };
if (isPresent(changeDetector)) {
this._changeDetector=changeDetector;
}
zone.initCallbacks({ zone.initCallbacks({
onErrorHandler: errorHandler, onErrorHandler: errorHandler,
onTurnDone: () => this.tick() onTurnDone: () => this.tick()
@ -32,4 +37,4 @@ export class LifeCycle {
this._changeDetector.checkNoChanges(); this._changeDetector.checkNoChanges();
} }
} }
} }

View File

@ -7,6 +7,7 @@ import {ListWrapper} from 'angular2/src/facade/collection';
import {PromiseWrapper} from 'angular2/src/facade/async'; import {PromiseWrapper} from 'angular2/src/facade/async';
import {bind, Inject} from 'angular2/di'; import {bind, Inject} from 'angular2/di';
import {TemplateConfig} from 'angular2/src/core/annotations/template_config'; import {TemplateConfig} from 'angular2/src/core/annotations/template_config';
import {LifeCycle} from 'angular2/src/core/life_cycle/life_cycle';
@Component({ @Component({
selector: 'hello-app', 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() { export function main() {
var fakeDoc, el, el2, testBindings; var fakeDoc, el, el2, testBindings;
@ -126,5 +142,14 @@ export function main() {
done(); 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();
});
});
}); });
} }