From 6f8fef4f132da8c31b8c275348bcb3da018692c7 Mon Sep 17 00:00:00 2001 From: vsavkin Date: Fri, 10 Apr 2015 10:09:16 -0700 Subject: [PATCH] feat(bootstrap): changed bootstrap to return ComponentRef --- modules/angular2/src/core/application.js | 10 ++- .../core/compiler/dynamic_component_loader.js | 2 +- .../src/core/compiler/element_injector.js | 26 ++----- .../angular2/test/core/application_spec.js | 74 +++++++++---------- .../src/largetable/largetable_benchmark.js | 3 +- modules/benchmarks/src/tree/tree_benchmark.js | 3 +- 6 files changed, 54 insertions(+), 64 deletions(-) diff --git a/modules/angular2/src/core/application.js b/modules/angular2/src/core/application.js index e8facc307e..0663e02b72 100644 --- a/modules/angular2/src/core/application.js +++ b/modules/angular2/src/core/application.js @@ -32,6 +32,7 @@ import {ProtoViewFactory} from 'angular2/src/core/compiler/proto_view_factory'; import {Renderer} from 'angular2/src/render/api'; import {DirectDomRenderer} from 'angular2/src/render/dom/direct_dom_renderer'; import * as rc from 'angular2/src/render/dom/compiler/compiler'; +import {ComponentRef} from 'angular2/src/core/compiler/element_injector'; import * as rvf from 'angular2/src/render/dom/view/view_factory'; import { @@ -244,7 +245,7 @@ function _createVmZone(givenReporter:Function): VmTurnZone { */ export function bootstrap(appComponentType: Type, componentInjectableBindings: List = null, - errorReporter: Function = null): Promise { + errorReporter: Function = null): Promise { BrowserDomAdapter.makeCurrent(); var bootstrapProcess = PromiseWrapper.completer(); @@ -255,14 +256,15 @@ export function bootstrap(appComponentType: Type, var appInjector = _createAppInjector(appComponentType, componentInjectableBindings, zone); - PromiseWrapper.then(appInjector.asyncGet(appChangeDetectorToken), - (appChangeDetector) => { + PromiseWrapper.then(appInjector.asyncGet(appComponentRefToken), + (componentRef) => { + var appChangeDetector = componentRef.hostView.changeDetector; // retrieve life cycle: may have already been created if injected in root component var lc = appInjector.get(LifeCycle); lc.registerWith(zone, appChangeDetector); lc.tick(); //the first tick that will bootstrap the app - bootstrapProcess.resolve(appInjector); + bootstrapProcess.resolve(componentRef); }, (err) => { diff --git a/modules/angular2/src/core/compiler/dynamic_component_loader.js b/modules/angular2/src/core/compiler/dynamic_component_loader.js index 87cf624480..1d903e47ae 100644 --- a/modules/angular2/src/core/compiler/dynamic_component_loader.js +++ b/modules/angular2/src/core/compiler/dynamic_component_loader.js @@ -79,7 +79,7 @@ export class DynamicComponentLoader { } _componentAppInjector(location, injector, services) { - var inj = isPresent(injector) ? injector : location.elementInjector.getLightDomAppInjector(); + var inj = isPresent(injector) ? injector : location.injector; return isPresent(services) ? inj.createChild(services) : inj; } diff --git a/modules/angular2/src/core/compiler/element_injector.js b/modules/angular2/src/core/compiler/element_injector.js index e65d0dad41..d42e49d4a2 100644 --- a/modules/angular2/src/core/compiler/element_injector.js +++ b/modules/angular2/src/core/compiler/element_injector.js @@ -27,11 +27,15 @@ export class ElementRef { } get hostView() { - return this.elementInjector.getHostView(); + return this.elementInjector._preBuiltObjects.view; + } + + get injector() { + return this.elementInjector._lightDomAppInjector; } get boundElementIndex() { - return this.elementInjector.getBoundElementIndex(); + return this.elementInjector._proto.index; } } @@ -608,21 +612,11 @@ export class ElementInjector extends TreeNode { return this._getDirectiveByKeyId(Key.get(type).id) !== _undefined; } - hasPreBuiltObject(type:Type):boolean { - var pb = this._getPreBuiltObjectByKeyId(Key.get(type).id); - return pb !== _undefined && isPresent(pb); - } - /** Gets the NgElement associated with this ElementInjector */ getNgElement() { return this._preBuiltObjects.element; } - /** Gets the View associated with this ElementInjector */ - getHostView() { - return this._preBuiltObjects.view; - } - getComponent() { if (this._proto._binding0IsComponent) { return this._obj0; @@ -635,10 +629,6 @@ export class ElementInjector extends TreeNode { return this._dynamicallyCreatedComponent; } - getLightDomAppInjector() { - return this._lightDomAppInjector; - } - directParent(): ElementInjector { return this._proto.distanceToParent < 2 ? this.parent : null; } @@ -699,10 +689,6 @@ export class ElementInjector extends TreeNode { return obj; } - getBoundElementIndex() { - return this._proto.index; - } - _getByDependency(dep:DirectiveDependency, requestor:Key) { if (isPresent(dep.eventEmitterName)) return this._buildEventEmitter(dep); if (isPresent(dep.propSetterName)) return this._buildPropSetter(dep); diff --git a/modules/angular2/test/core/application_spec.js b/modules/angular2/test/core/application_spec.js index 7e79fc9575..fc5423203e 100644 --- a/modules/angular2/test/core/application_spec.js +++ b/modules/angular2/test/core/application_spec.js @@ -88,24 +88,24 @@ export function main() { describe('bootstrap factory method', () => { it('should throw if no View found', inject([AsyncTestCompleter], (async) => { - var injectorPromise = bootstrap(HelloRootMissingTemplate, testBindings, (e,t) => {throw e;}); - PromiseWrapper.then(injectorPromise, null, (reason) => { + var refPromise = bootstrap(HelloRootMissingTemplate, testBindings, (e,t) => {throw e;}); + PromiseWrapper.then(refPromise, null, (reason) => { expect(reason.message).toContain('No template found for HelloRootMissingTemplate'); async.done(); }); })); it('should throw if bootstrapped Directive is not a Component', inject([AsyncTestCompleter], (async) => { - var injectorPromise = bootstrap(HelloRootDirectiveIsNotCmp, testBindings, (e,t) => {throw e;}); - PromiseWrapper.then(injectorPromise, null, (reason) => { + var refPromise = bootstrap(HelloRootDirectiveIsNotCmp, testBindings, (e,t) => {throw e;}); + PromiseWrapper.then(refPromise, null, (reason) => { expect(reason.message).toContain(`Could not load 'HelloRootDirectiveIsNotCmp' because it is not a component.`); async.done(); }); })); it('should throw if no element is found', inject([AsyncTestCompleter], (async) => { - var injectorPromise = bootstrap(HelloRootCmp, [], (e,t) => {throw e;}); - PromiseWrapper.then(injectorPromise, null, (reason) => { + var refPromise = bootstrap(HelloRootCmp, [], (e,t) => {throw e;}); + PromiseWrapper.then(refPromise, null, (reason) => { expect(reason.message).toContain( 'The app selector "hello-app" did not match any elements'); async.done(); @@ -113,82 +113,82 @@ export function main() { })); it('should create an injector promise', () => { - var injectorPromise = bootstrap(HelloRootCmp, testBindings); - expect(injectorPromise).not.toBe(null); + var refPromise = bootstrap(HelloRootCmp, testBindings); + expect(refPromise).not.toBe(null); }); it('should resolve an injector promise and contain bindings', inject([AsyncTestCompleter], (async) => { - var injectorPromise = bootstrap(HelloRootCmp, testBindings); - injectorPromise.then((injector) => { - expect(injector.get(appElementToken)).toBe(el); + var refPromise = bootstrap(HelloRootCmp, testBindings); + refPromise.then((ref) => { + expect(ref.injector.get(appElementToken)).toBe(el); async.done(); }); })); it('should provide the application component in the injector', inject([AsyncTestCompleter], (async) => { - var injectorPromise = bootstrap(HelloRootCmp, testBindings); - injectorPromise.then((injector) => { - expect(injector.get(HelloRootCmp)).toBeAnInstanceOf(HelloRootCmp); + var refPromise = bootstrap(HelloRootCmp, testBindings); + refPromise.then((ref) => { + expect(ref.injector.get(HelloRootCmp)).toBeAnInstanceOf(HelloRootCmp); async.done(); }); })); it('should display hello world', inject([AsyncTestCompleter], (async) => { - var injectorPromise = bootstrap(HelloRootCmp, testBindings); - injectorPromise.then((injector) => { - expect(injector.get(appElementToken)).toHaveText('hello world!'); + var refPromise = bootstrap(HelloRootCmp, testBindings); + refPromise.then((ref) => { + expect(ref.injector.get(appElementToken)).toHaveText('hello world!'); async.done(); }); })); it('should support multiple calls to bootstrap', inject([AsyncTestCompleter], (async) => { - var injectorPromise1 = bootstrap(HelloRootCmp, testBindings); - var injectorPromise2 = bootstrap(HelloRootCmp2, testBindings); - PromiseWrapper.all([injectorPromise1, injectorPromise2]).then((injectors) => { - expect(injectors[0].get(appElementToken)).toHaveText('hello world!'); - expect(injectors[1].get(appElementToken)).toHaveText('hello world, again!'); + var refPromise1 = bootstrap(HelloRootCmp, testBindings); + var refPromise2 = bootstrap(HelloRootCmp2, testBindings); + PromiseWrapper.all([refPromise1, refPromise2]).then((refs) => { + expect(refs[0].injector.get(appElementToken)).toHaveText('hello world!'); + expect(refs[1].injector.get(appElementToken)).toHaveText('hello world, again!'); async.done(); }); })); it("should make the provided bindings available to the application component", inject([AsyncTestCompleter], (async) => { - var injectorPromise = bootstrap(HelloRootCmp3, [ + var refPromise = bootstrap(HelloRootCmp3, [ testBindings, bind("appBinding").toValue("BoundValue") ]); - injectorPromise.then((injector) => { - expect(injector.get(HelloRootCmp3).appBinding).toEqual("BoundValue"); + refPromise.then((ref) => { + expect(ref.injector.get(HelloRootCmp3).appBinding).toEqual("BoundValue"); async.done(); }); })); it("should avoid cyclic dependencies when root component requires Lifecycle through DI", inject([AsyncTestCompleter], (async) => { - var injectorPromise = bootstrap(HelloRootCmp4, testBindings); + var refPromise = bootstrap(HelloRootCmp4, testBindings); - injectorPromise.then((injector) => { - expect(injector.get(HelloRootCmp4).lc).toBe(injector.get(LifeCycle)); + refPromise.then((ref) => { + expect(ref.injector.get(HelloRootCmp4).lc).toBe(ref.injector.get(LifeCycle)); async.done(); }); })); it("should support shadow dom content tag", inject([AsyncTestCompleter], (async) => { - var injectorPromise = bootstrap(HelloRootCmpContent, testBindings); - injectorPromise.then((injector) => { - expect(injector.get(appElementToken)).toHaveText('before: loading after: done'); + var refPromise = bootstrap(HelloRootCmpContent, testBindings); + refPromise.then((ref) => { + expect(ref.injector.get(appElementToken)).toHaveText('before: loading after: done'); async.done(); }); })); it('should register each application with the testability registry', inject([AsyncTestCompleter], (async) => { - var injectorPromise1 = bootstrap(HelloRootCmp, testBindings); - var injectorPromise2 = bootstrap(HelloRootCmp2, testBindings); + var refPromise1 = bootstrap(HelloRootCmp, testBindings); + var refPromise2 = bootstrap(HelloRootCmp2, testBindings); - PromiseWrapper.all([injectorPromise1, injectorPromise2]).then((injectors) => { - var registry = injectors[0].get(TestabilityRegistry); + PromiseWrapper.all([refPromise1, refPromise2]).then((refs) => { + var registry = refs[0].injector.get(TestabilityRegistry); PromiseWrapper.all([ - injectors[0].asyncGet(Testability), - injectors[1].asyncGet(Testability)]).then((testabilities) => { + refs[0].injector.asyncGet(Testability), + refs[1].injector.asyncGet(Testability)]).then((testabilities) => { expect(registry.findTestabilityInTree(el)).toEqual(testabilities[0]); expect(registry.findTestabilityInTree(el2)).toEqual(testabilities[1]); async.done(); diff --git a/modules/benchmarks/src/largetable/largetable_benchmark.js b/modules/benchmarks/src/largetable/largetable_benchmark.js index 3c24c97385..2a564ba96b 100644 --- a/modules/benchmarks/src/largetable/largetable_benchmark.js +++ b/modules/benchmarks/src/largetable/largetable_benchmark.js @@ -142,7 +142,8 @@ export function main() { function noop() {} function initNg2() { - bootstrap(AppComponent, _createBindings()).then((injector) => { + bootstrap(AppComponent, _createBindings()).then((ref) => { + var injector = ref.injector; app = injector.get(AppComponent); lifecycle = injector.get(LifeCycle); bindAction('#ng2DestroyDom', ng2DestroyDom); diff --git a/modules/benchmarks/src/tree/tree_benchmark.js b/modules/benchmarks/src/tree/tree_benchmark.js index 004e063a48..37ec613195 100644 --- a/modules/benchmarks/src/tree/tree_benchmark.js +++ b/modules/benchmarks/src/tree/tree_benchmark.js @@ -120,7 +120,8 @@ export function main() { function noop() {} function initNg2() { - bootstrap(AppComponent, createBindings()).then((injector) => { + bootstrap(AppComponent, createBindings()).then((ref) => { + var injector = ref.injector; lifeCycle = injector.get(LifeCycle); app = injector.get(AppComponent);