diff --git a/modules/angular2/src/core/annotations/events.js b/modules/angular2/src/core/annotations/di.js similarity index 57% rename from modules/angular2/src/core/annotations/events.js rename to modules/angular2/src/core/annotations/di.js index 75d4d9f8e7..c9f54074d2 100644 --- a/modules/angular2/src/core/annotations/events.js +++ b/modules/angular2/src/core/annotations/di.js @@ -13,3 +13,16 @@ export class EventEmitter extends DependencyAnnotation { this.eventName = eventName; } } + +/** + * The directive can inject a property setter that would allow setting this property on the + * host element + */ +export class PropertySetter extends DependencyAnnotation { + propName: string; + @CONST() + constructor(propName) { + super(); + this.propName = propName; + } +} diff --git a/modules/angular2/src/core/application.js b/modules/angular2/src/core/application.js index 2a6e309359..cca8518ad8 100644 --- a/modules/angular2/src/core/application.js +++ b/modules/angular2/src/core/application.js @@ -59,7 +59,7 @@ function _injectorBindings(appComponentType): List { }, [appComponentAnnotatedTypeToken, appDocumentToken]), bind(appViewToken).toAsyncFactory((changeDetection, compiler, injector, appElement, - appComponentAnnotatedType, strategy, eventManager) => { + appComponentAnnotatedType, strategy, eventManager, reflector) => { return compiler.compile(appComponentAnnotatedType.type).then( (protoView) => { var appProtoView = ProtoView.createRootProtoView(protoView, appElement, @@ -68,12 +68,12 @@ function _injectorBindings(appComponentType): List { // The light Dom of the app element is not considered part of // the angular application. Thus the context and lightDomInjector are // empty. - var view = appProtoView.instantiate(null, eventManager); + var view = appProtoView.instantiate(null, eventManager, reflector); view.hydrate(injector, null, new Object()); return view; }); }, [ChangeDetection, Compiler, Injector, appElementToken, appComponentAnnotatedTypeToken, - ShadowDomStrategy, EventManager]), + ShadowDomStrategy, EventManager, Reflector]), bind(appChangeDetectorToken).toFactory((rootView) => rootView.changeDetector, [appViewToken]), diff --git a/modules/angular2/src/core/compiler/element_injector.js b/modules/angular2/src/core/compiler/element_injector.js index 2ab87348da..8e90a76a0a 100644 --- a/modules/angular2/src/core/compiler/element_injector.js +++ b/modules/angular2/src/core/compiler/element_injector.js @@ -3,13 +3,14 @@ import {Math} from 'angular2/src/facade/math'; import {List, ListWrapper, MapWrapper} from 'angular2/src/facade/collection'; import {Injector, Key, Dependency, bind, Binding, NoProviderError, ProviderError, CyclicDependencyError} from 'angular2/di'; import {Parent, Ancestor} from 'angular2/src/core/annotations/visibility'; -import {EventEmitter} from 'angular2/src/core/annotations/events'; +import {EventEmitter, PropertySetter} from 'angular2/src/core/annotations/di'; import {View, ProtoView} from 'angular2/src/core/compiler/view'; import {LightDom, SourceLightDom, DestinationLightDom} from 'angular2/src/core/compiler/shadow_dom_emulation/light_dom'; import {ViewContainer} from 'angular2/src/core/compiler/view_container'; import {NgElement} from 'angular2/src/core/dom/element'; import {Directive, onChange, onDestroy} from 'angular2/src/core/annotations/annotations' import {BindingPropagationConfig} from 'angular2/src/core/compiler/binding_propagation_config' +import {Reflector} from 'angular2/src/reflection/reflection'; var _MAX_DIRECTIVE_CONSTRUCTION_COUNTER = 10; @@ -90,18 +91,22 @@ class TreeNode { export class DirectiveDependency extends Dependency { depth:int; eventEmitterName:string; + propSetterName:string; constructor(key:Key, asPromise:boolean, lazy:boolean, optional:boolean, - properties:List, depth:int, eventEmitterName: string) { + properties:List, depth:int, eventEmitterName: string, propSetterName: string) { super(key, asPromise, lazy, optional, properties); this.depth = depth; this.eventEmitterName = eventEmitterName; + this.propSetterName = propSetterName; } static createFrom(d:Dependency):Dependency { return new DirectiveDependency(d.key, d.asPromise, d.lazy, d.optional, d.properties, DirectiveDependency._depth(d.properties), - DirectiveDependency._eventEmitterName(d.properties)); + DirectiveDependency._eventEmitterName(d.properties), + DirectiveDependency._propSetterName(d.properties) + ); } static _depth(properties):int { @@ -119,6 +124,15 @@ export class DirectiveDependency extends Dependency { } return null; } + + static _propSetterName(properties):string { + for (var i = 0; i < properties.length; i++) { + if (properties[i] instanceof PropertySetter) { + return properties[i].propName; + } + } + return null; + } } export class DirectiveBinding extends Binding { @@ -256,8 +270,9 @@ export class ProtoElementInjector { } } - instantiate(parent:ElementInjector, host:ElementInjector, eventCallbacks):ElementInjector { - return new ElementInjector(this, parent, host, eventCallbacks); + instantiate(parent:ElementInjector, host:ElementInjector, eventCallbacks, + reflector: Reflector):ElementInjector { + return new ElementInjector(this, parent, host, eventCallbacks, reflector); } directParent(): ProtoElementInjector { @@ -311,7 +326,10 @@ export class ElementInjector extends TreeNode { _preBuiltObjects; _constructionCounter; _eventCallbacks; - constructor(proto:ProtoElementInjector, parent:ElementInjector, host:ElementInjector, eventCallbacks: Map) { + _refelector: Reflector; + + constructor(proto:ProtoElementInjector, parent:ElementInjector, host:ElementInjector, + eventCallbacks: Map, reflector: Reflector) { super(parent); if (isPresent(parent) && isPresent(host)) { throw new BaseException('Only either parent or host is allowed'); @@ -324,6 +342,7 @@ export class ElementInjector extends TreeNode { } this._proto = proto; + this._refelector = reflector; //we cannot call clearDirectives because fields won't be detected this._preBuiltObjects = null; @@ -488,6 +507,7 @@ export class ElementInjector extends TreeNode { _getByDependency(dep:DirectiveDependency, requestor:Key) { if (isPresent(dep.eventEmitterName)) return this._buildEventEmitter(dep); + if (isPresent(dep.propSetterName)) return this._buildPropSetter(dep); return this._getByKey(dep.key, dep.depth, dep.optional, requestor); } @@ -502,6 +522,13 @@ export class ElementInjector extends TreeNode { return (_) => {}; } + _buildPropSetter(dep) { + var ngElement = this._getPreBuiltObjectByKeyId(StaticKeys.instance().ngElementId); + var domElement = ngElement.domElement; + var setter = this._refelector.setter(dep.propSetterName); + return function(v) { setter(domElement, v) }; + } + /* * It is fairly easy to annotate keys with metadata. * For example, key.metadata = 'directive'. diff --git a/modules/angular2/src/core/compiler/view.js b/modules/angular2/src/core/compiler/view.js index 968fff6735..89392cb396 100644 --- a/modules/angular2/src/core/compiler/view.js +++ b/modules/angular2/src/core/compiler/view.js @@ -18,6 +18,8 @@ import {ShadowDomStrategy} from './shadow_dom_strategy'; import {ViewPool} from './view_pool'; import {EventManager} from 'angular2/src/core/events/event_manager'; +import {Reflector} from 'angular2/src/reflection/reflection'; + const NG_BINDING_CLASS = 'ng-binding'; const NG_BINDING_CLASS_SELECTOR = '.ng-binding'; @@ -298,19 +300,23 @@ export class ProtoView { } // TODO(rado): hostElementInjector should be moved to hydrate phase. - instantiate(hostElementInjector: ElementInjector, eventManager: EventManager):View { - if (this._viewPool.length() == 0) this._preFillPool(hostElementInjector, eventManager); + instantiate(hostElementInjector: ElementInjector, eventManager: EventManager, + reflector: Reflector):View { + if (this._viewPool.length() == 0) this._preFillPool(hostElementInjector, eventManager, + reflector); var view = this._viewPool.pop(); - return isPresent(view) ? view : this._instantiate(hostElementInjector, eventManager); + return isPresent(view) ? view : this._instantiate(hostElementInjector, eventManager, reflector); } - _preFillPool(hostElementInjector: ElementInjector, eventManager: EventManager) { + _preFillPool(hostElementInjector: ElementInjector, eventManager: EventManager, + reflector: Reflector) { for (var i = 0; i < VIEW_POOL_PREFILL; i++) { - this._viewPool.push(this._instantiate(hostElementInjector, eventManager)); + this._viewPool.push(this._instantiate(hostElementInjector, eventManager, reflector)); } } - _instantiate(hostElementInjector: ElementInjector, eventManager: EventManager): View { + _instantiate(hostElementInjector: ElementInjector, eventManager: EventManager, + reflector: Reflector): View { var rootElementClone = this.instantiateInPlace ? this.element : DOM.importIntoDoc(this.element); var elementsWithBindingsDynamic; if (this.isTemplateElement) { @@ -362,9 +368,11 @@ export class ProtoView { if (isPresent(protoElementInjector)) { if (isPresent(protoElementInjector.parent)) { var parentElementInjector = elementInjectors[protoElementInjector.parent.index]; - elementInjector = protoElementInjector.instantiate(parentElementInjector, null, binder.events); + elementInjector = protoElementInjector.instantiate(parentElementInjector, null, + binder.events, reflector); } else { - elementInjector = protoElementInjector.instantiate(null, hostElementInjector, binder.events); + elementInjector = protoElementInjector.instantiate(null, hostElementInjector, + binder.events, reflector); ListWrapper.push(rootElementInjectors, elementInjector); } } @@ -391,7 +399,7 @@ export class ProtoView { var bindingPropagationConfig = null; if (isPresent(binder.componentDirective)) { var strategy = this.shadowDomStrategy; - var childView = binder.nestedProtoView.instantiate(elementInjector, eventManager); + var childView = binder.nestedProtoView.instantiate(elementInjector, eventManager, reflector); view.changeDetector.addChild(childView.changeDetector); lightDom = strategy.constructLightDom(view, childView, element); @@ -407,7 +415,7 @@ export class ProtoView { if (isPresent(binder.viewportDirective)) { var destLightDom = this._directParentElementLightDom(protoElementInjector, preBuiltObjects); viewContainer = new ViewContainer(view, element, binder.nestedProtoView, elementInjector, - eventManager, destLightDom); + eventManager, reflector, destLightDom); ListWrapper.push(viewContainers, viewContainer); } diff --git a/modules/angular2/src/core/compiler/view_container.js b/modules/angular2/src/core/compiler/view_container.js index ac9365c6f6..f92480ad4a 100644 --- a/modules/angular2/src/core/compiler/view_container.js +++ b/modules/angular2/src/core/compiler/view_container.js @@ -6,6 +6,7 @@ import {Injector} from 'angular2/di'; import * as eiModule from 'angular2/src/core/compiler/element_injector'; import {isPresent, isBlank} from 'angular2/src/facade/lang'; import {EventManager} from 'angular2/src/core/events/event_manager'; +import {Reflector} from 'angular2/src/reflection/reflection'; export class ViewContainer { parentView: viewModule.View; @@ -14,17 +15,24 @@ export class ViewContainer { _views: List; _lightDom: any; _eventManager: EventManager; + _reflector: Reflector; elementInjector: eiModule.ElementInjector; appInjector: Injector; hostElementInjector: eiModule.ElementInjector; - constructor(parentView: viewModule.View, templateElement, defaultProtoView: viewModule.ProtoView, - elementInjector: eiModule.ElementInjector, eventManager: EventManager, lightDom = null) { + constructor(parentView: viewModule.View, + templateElement, + defaultProtoView: viewModule.ProtoView, + elementInjector: eiModule.ElementInjector, + eventManager: EventManager, + reflector: Reflector, + lightDom = null) { this.parentView = parentView; this.templateElement = templateElement; this.defaultProtoView = defaultProtoView; this.elementInjector = elementInjector; this._lightDom = lightDom; + this._reflector = reflector; // The order in this list matches the DOM order. this._views = []; @@ -73,7 +81,8 @@ export class ViewContainer { if (!this.hydrated()) throw new BaseException( 'Cannot create views on a dehydrated ViewContainer'); // TODO(rado): replace with viewFactory. - var newView = this.defaultProtoView.instantiate(this.hostElementInjector, this._eventManager); + var newView = this.defaultProtoView.instantiate(this.hostElementInjector, this._eventManager, + this._reflector); // insertion must come before hydration so that element injector trees are attached. this.insert(newView, atIndex); newView.hydrate(this.appInjector, this.hostElementInjector, this.parentView.context); diff --git a/modules/angular2/test/core/compiler/element_injector_spec.js b/modules/angular2/test/core/compiler/element_injector_spec.js index 490397e4e2..d32e7376ae 100644 --- a/modules/angular2/test/core/compiler/element_injector_spec.js +++ b/modules/angular2/test/core/compiler/element_injector_spec.js @@ -1,9 +1,9 @@ -import {describe, ddescribe, it, iit, xit, xdescribe, expect, beforeEach, SpyObject, proxy} from 'angular2/test_lib'; +import {describe, ddescribe, it, iit, xit, xdescribe, expect, beforeEach, SpyObject, proxy, el} from 'angular2/test_lib'; import {isBlank, isPresent, FIELD, IMPLEMENTS} from 'angular2/src/facade/lang'; import {ListWrapper, MapWrapper, List} from 'angular2/src/facade/collection'; import {ProtoElementInjector, PreBuiltObjects, DirectiveBinding} from 'angular2/src/core/compiler/element_injector'; import {Parent, Ancestor} from 'angular2/src/core/annotations/visibility'; -import {EventEmitter} from 'angular2/src/core/annotations/events'; +import {EventEmitter, PropertySetter} from 'angular2/src/core/annotations/di'; import {onDestroy} from 'angular2/src/core/annotations/annotations'; import {Optional, Injector, Inject, bind} from 'angular2/di'; import {View} from 'angular2/src/core/compiler/view'; @@ -12,6 +12,7 @@ import {NgElement} from 'angular2/src/core/dom/element'; import {LightDom, SourceLightDom, DestinationLightDom} from 'angular2/src/core/compiler/shadow_dom_emulation/light_dom'; import {Directive} from 'angular2/src/core/annotations/annotations'; import {BindingPropagationConfig} from 'angular2/src/core/compiler/binding_propagation_config'; +import {reflector} from 'angular2/src/reflection/reflection'; @proxy @IMPLEMENTS(View) @@ -74,6 +75,17 @@ class NeedsEventEmitter { } } +class NeedsPropertySetter { + propSetter; + constructor(@PropertySetter('title') propSetter: Function) { + this.propSetter = propSetter; + } + + setProp(value) { + this.propSetter(value); + } +} + class A_Needs_B { constructor(dep){} } @@ -118,7 +130,7 @@ export function main() { if (isBlank(lightDomAppInjector)) lightDomAppInjector = new Injector([]); var proto = new ProtoElementInjector(null, 0, bindings, isPresent(shadowDomAppInjector)); - var inj = proto.instantiate(null, null, null); + var inj = proto.instantiate(null, null, null, reflector); var preBuilt = isPresent(preBuiltObjects) ? preBuiltObjects : defaultPreBuiltObjects; inj.instantiateDirectives(lightDomAppInjector, shadowDomAppInjector, preBuilt); @@ -131,12 +143,12 @@ export function main() { var inj = new Injector([]); var protoParent = new ProtoElementInjector(null, 0, parentBindings); - var parent = protoParent.instantiate(null, null, null); + var parent = protoParent.instantiate(null, null, null, reflector); parent.instantiateDirectives(inj, null, parentPreBuildObjects); var protoChild = new ProtoElementInjector(protoParent, 1, childBindings, false, 1); - var child = protoChild.instantiate(parent, null, null); + var child = protoChild.instantiate(parent, null, null, reflector); child.instantiateDirectives(inj, null, defaultPreBuiltObjects); return child; @@ -149,11 +161,11 @@ export function main() { var shadowInj = inj.createChild([]); var protoParent = new ProtoElementInjector(null, 0, hostBindings, true); - var host = protoParent.instantiate(null, null, null); + var host = protoParent.instantiate(null, null, null, reflector); host.instantiateDirectives(inj, shadowInj, hostPreBuildObjects); var protoChild = new ProtoElementInjector(protoParent, 0, shadowBindings, false, 1); - var shadow = protoChild.instantiate(null, host, null); + var shadow = protoChild.instantiate(null, host, null, reflector); shadow.instantiateDirectives(shadowInj, null, null); return shadow; @@ -186,9 +198,9 @@ export function main() { var protoChild1 = new ProtoElementInjector(protoParent, 1, []); var protoChild2 = new ProtoElementInjector(protoParent, 2, []); - var p = protoParent.instantiate(null, null, null); - var c1 = protoChild1.instantiate(p, null, null); - var c2 = protoChild2.instantiate(p, null, null); + var p = protoParent.instantiate(null, null, null, reflector); + var c1 = protoChild1.instantiate(p, null, null, reflector); + var c2 = protoChild2.instantiate(p, null, null, reflector); expect(humanize(p, [ [p, 'parent'], @@ -203,8 +215,8 @@ export function main() { var protoParent = new ProtoElementInjector(null, 0, []); var protoChild = new ProtoElementInjector(protoParent, 1, [], false, distance); - var p = protoParent.instantiate(null, null, null); - var c = protoChild.instantiate(p, null, null); + var p = protoParent.instantiate(null, null, null, reflector); + var c = protoChild.instantiate(p, null, null, reflector); expect(c.directParent()).toEqual(p); }); @@ -214,8 +226,8 @@ export function main() { var protoParent = new ProtoElementInjector(null, 0, []); var protoChild = new ProtoElementInjector(protoParent, 1, [], false, distance); - var p = protoParent.instantiate(null, null, null); - var c = protoChild.instantiate(p, null, null); + var p = protoParent.instantiate(null, null, null, reflector); + var c = protoChild.instantiate(p, null, null, reflector); expect(c.directParent()).toEqual(null); }); @@ -422,7 +434,7 @@ export function main() { }); it('should return viewContainer', function () { - var viewContainer = new ViewContainer(null, null, null, null, null); + var viewContainer = new ViewContainer(null, null, null, null, null, null); var inj = injector([], null, null, new PreBuiltObjects(null, null, viewContainer, null, null)); expect(inj.get(ViewContainer)).toEqual(viewContainer); @@ -475,5 +487,19 @@ export function main() { expect(inj.hasEventEmitter('move')).toBe(false); }); }); + + describe('property setter', () => { + it('should be injectable and callable', () => { + var div = el('
'); + var ngElement = new NgElement(div); + + var preBuildObject = new PreBuiltObjects(null, ngElement, null, null, null); + var inj = injector([NeedsPropertySetter], null, null, preBuildObject); + inj.get(NeedsPropertySetter).setProp('foobar'); + + expect(div.title).toEqual('foobar'); + }); + }); + }); } diff --git a/modules/angular2/test/core/compiler/integration_spec.js b/modules/angular2/test/core/compiler/integration_spec.js index 586bc2702a..9f067f7601 100644 --- a/modules/angular2/test/core/compiler/integration_spec.js +++ b/modules/angular2/test/core/compiler/integration_spec.js @@ -27,6 +27,8 @@ import {If} from 'angular2/src/directives/if'; import {ViewContainer} from 'angular2/src/core/compiler/view_container'; +import {reflector} from 'angular2/src/reflection/reflection'; + export function main() { describe('integration tests', function() { var compiler, tplResolver; @@ -55,7 +57,7 @@ export function main() { var view, ctx, cd; function createView(pv) { ctx = new MyComp(); - view = pv.instantiate(null, null); + view = pv.instantiate(null, null, reflector); view.hydrate(new Injector([]), null, ctx); cd = view.changeDetector; } diff --git a/modules/angular2/test/core/compiler/pipeline/element_binder_builder_spec.js b/modules/angular2/test/core/compiler/pipeline/element_binder_builder_spec.js index d7448c3ec6..e704f5d806 100644 --- a/modules/angular2/test/core/compiler/pipeline/element_binder_builder_spec.js +++ b/modules/angular2/test/core/compiler/pipeline/element_binder_builder_spec.js @@ -82,7 +82,7 @@ export function main() { function instantiateView(protoView) { evalContext = new Context(); - view = protoView.instantiate(null, null); + view = protoView.instantiate(null, null, null); view.hydrate(new Injector([]), null, evalContext); changeDetector = view.changeDetector; } diff --git a/modules/angular2/test/core/compiler/shadow_dom/shadow_dom_emulation_integration_spec.js b/modules/angular2/test/core/compiler/shadow_dom/shadow_dom_emulation_integration_spec.js index 4aef354585..d227eada69 100644 --- a/modules/angular2/test/core/compiler/shadow_dom/shadow_dom_emulation_integration_spec.js +++ b/modules/angular2/test/core/compiler/shadow_dom/shadow_dom_emulation_integration_spec.js @@ -32,6 +32,8 @@ import {ViewContainer} from 'angular2/src/core/compiler/view_container'; import {BrowserDomAdapter} from 'angular2/src/dom/browser_adapter'; +import {reflector} from 'angular2/src/reflection/reflection'; + export function main() { BrowserDomAdapter.makeCurrent(); describe('integration tests', function() { @@ -352,7 +354,7 @@ class MyComp { } function createView(pv) { - var view = pv.instantiate(null, null); + var view = pv.instantiate(null, null, reflector); view.hydrate(new Injector([]), null, {}); return view; } diff --git a/modules/angular2/test/core/compiler/shadow_dom_strategy_spec.js b/modules/angular2/test/core/compiler/shadow_dom_strategy_spec.js index 65e8620cb2..44a26ee75c 100644 --- a/modules/angular2/test/core/compiler/shadow_dom_strategy_spec.js +++ b/modules/angular2/test/core/compiler/shadow_dom_strategy_spec.js @@ -37,7 +37,7 @@ export function main() { var host = el('
'); var nodes = el('
view
'); var pv = new ProtoView(nodes, new DynamicProtoChangeDetector(null), null); - var view = pv.instantiate(null, null); + var view = pv.instantiate(null, null, null); strategy.attachTemplate(host, view); var shadowRoot = DOM.getShadowRoot(host); @@ -83,7 +83,7 @@ export function main() { var host = el('
original content
'); var nodes = el('
view
'); var pv = new ProtoView(nodes, new DynamicProtoChangeDetector(null), null); - var view = pv.instantiate(null, null); + var view = pv.instantiate(null, null, null); strategy.attachTemplate(host, view); var firstChild = DOM.firstChild(host); @@ -218,7 +218,7 @@ export function main() { var host = el('
original content
'); var nodes = el('
view
'); var pv = new ProtoView(nodes, new DynamicProtoChangeDetector(null), null); - var view = pv.instantiate(null, null); + var view = pv.instantiate(null, null, null); strategy.attachTemplate(host, view); var firstChild = DOM.firstChild(host); diff --git a/modules/angular2/test/core/compiler/view_container_spec.js b/modules/angular2/test/core/compiler/view_container_spec.js index 1861ee74f5..e396699ba9 100644 --- a/modules/angular2/test/core/compiler/view_container_spec.js +++ b/modules/angular2/test/core/compiler/view_container_spec.js @@ -8,6 +8,7 @@ import {Injector} from 'angular2/di'; import {ProtoElementInjector, ElementInjector} from 'angular2/src/core/compiler/element_injector'; import {NativeShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy'; import {DynamicProtoChangeDetector, ChangeDetector, Lexer, Parser} from 'angular2/change_detection'; +import {reflector} from 'angular2/src/reflection/reflection'; function createView(nodes) { var view = new View(null, nodes, new DynamicProtoChangeDetector(null), MapWrapper.create()); @@ -71,8 +72,9 @@ export function main() { parentView = createView([dom.childNodes[0]]); protoView = new ProtoView(el('
hi
'), new DynamicProtoChangeDetector(null), new NativeShadowDomStrategy(null)); - elementInjector = new ElementInjector(null, null, null, null); - viewContainer = new ViewContainer(parentView, insertionElement, protoView, elementInjector, null); + elementInjector = new ElementInjector(null, null, null, null, reflector); + viewContainer = new ViewContainer(parentView, insertionElement, protoView, elementInjector, + null, reflector); customViewWithOneNode = createView([el('
single
')]); customViewWithTwoNodes = createView([el('
one
'), el('
two
')]); }); @@ -217,7 +219,7 @@ export function main() { new DynamicProtoChangeDetector(null), new NativeShadowDomStrategy(null)); pv.bindElement(new ProtoElementInjector(null, 1, [SomeDirective])); pv.bindTextNode(0, parser.parseBinding('foo', null)); - fancyView = pv.instantiate(null, null); + fancyView = pv.instantiate(null, null, reflector); }); it('hydrating should update rootElementInjectors and parent change detector', () => { diff --git a/modules/angular2/test/core/compiler/view_spec.js b/modules/angular2/test/core/compiler/view_spec.js index 0582443083..3821fe4c5c 100644 --- a/modules/angular2/test/core/compiler/view_spec.js +++ b/modules/angular2/test/core/compiler/view_spec.js @@ -6,16 +6,16 @@ import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_meta import {Component, Decorator, Viewport, Directive, onChange} from 'angular2/src/core/annotations/annotations'; import {Lexer, Parser, DynamicProtoChangeDetector, ChangeDetector} from 'angular2/change_detection'; -import {EventEmitter} from 'angular2/src/core/annotations/events'; +import {EventEmitter} from 'angular2/src/core/annotations/di'; import {List, MapWrapper} from 'angular2/src/facade/collection'; import {DOM} from 'angular2/src/dom/dom_adapter'; import {int, IMPLEMENTS} from 'angular2/src/facade/lang'; import {Injector} from 'angular2/di'; import {View} from 'angular2/src/core/compiler/view'; import {ViewContainer} from 'angular2/src/core/compiler/view_container'; -import {reflector} from 'angular2/src/reflection/reflection'; import {VmTurnZone} from 'angular2/src/core/zone/vm_turn_zone'; import {EventManager, DomEventsPlugin} from 'angular2/src/core/events/event_manager'; +import {Reflector, reflector} from 'angular2/src/reflection/reflection'; @proxy @IMPLEMENTS(ViewContainer) @@ -45,7 +45,7 @@ export function main() { function createView(protoView, eventManager: EventManager = null) { var ctx = new MyEvaluationContext(); - var view = protoView.instantiate(null, eventManager); + var view = protoView.instantiate(null, eventManager, reflector); view.hydrate(null, null, ctx); return view; } @@ -60,7 +60,7 @@ export function main() { var view; beforeEach(() => { var pv = new ProtoView(el('
'), new DynamicProtoChangeDetector(null), null); - view = pv.instantiate(null, null); + view = pv.instantiate(null, null, reflector); }); it('should be dehydrated by default', () => { @@ -90,7 +90,7 @@ export function main() { var fakeView = new FakeView(); pv.returnToPool(fakeView); - expect(pv.instantiate(null, null)).toBe(fakeView); + expect(pv.instantiate(null, null, reflector)).toBe(fakeView); }); }); @@ -135,7 +135,7 @@ export function main() { it('should collect the root node in the ProtoView element', () => { var pv = new ProtoView(templateAwareCreateElement('
'), new DynamicProtoChangeDetector(null), null); - var view = pv.instantiate(null, null); + var view = pv.instantiate(null, null, reflector); view.hydrate(null, null, null); expect(view.nodes.length).toBe(1); expect(view.nodes[0].getAttribute('id')).toEqual('1'); @@ -149,7 +149,7 @@ export function main() { pv.bindElement(null); pv.bindElementProperty(parser.parseBinding('a', null), 'prop', reflector.setter('prop')); - var view = pv.instantiate(null, null); + var view = pv.instantiate(null, null, reflector); view.hydrate(null, null, null); expect(view.bindElements.length).toEqual(1); expect(view.bindElements[0]).toBe(view.nodes[0]); @@ -161,7 +161,7 @@ export function main() { pv.bindElement(null); pv.bindElementProperty(parser.parseBinding('b', null), 'a', reflector.setter('a')); - var view = pv.instantiate(null, null); + var view = pv.instantiate(null, null, reflector); view.hydrate(null, null, null); expect(view.bindElements.length).toEqual(1); expect(view.bindElements[0]).toBe(view.nodes[0].childNodes[1]); @@ -178,7 +178,7 @@ export function main() { pv.bindTextNode(0, parser.parseBinding('a', null)); pv.bindTextNode(2, parser.parseBinding('b', null)); - var view = pv.instantiate(null, null); + var view = pv.instantiate(null, null, reflector); view.hydrate(null, null, null); expect(view.textNodes.length).toEqual(2); expect(view.textNodes[0]).toBe(view.nodes[0].childNodes[0]); @@ -191,7 +191,7 @@ export function main() { pv.bindElement(null); pv.bindTextNode(0, parser.parseBinding('b', null)); - var view = pv.instantiate(null, null); + var view = pv.instantiate(null, null, reflector); view.hydrate(null, null, null); expect(view.textNodes.length).toEqual(1); expect(view.textNodes[0]).toBe(view.nodes[0].childNodes[1].childNodes[0]); @@ -206,16 +206,16 @@ export function main() { var pv = new ProtoView(template, new DynamicProtoChangeDetector(null), new NativeShadowDomStrategy(null)); pv.instantiateInPlace = true; - var view = pv.instantiate(null, null); + var view = pv.instantiate(null, null, reflector); view.hydrate(null, null, null); expect(view.nodes[0]).toBe(template); }); it('should be off by default.', () => { var template = el('
') - var view = new ProtoView(template, new DynamicProtoChangeDetector(null), + var pv = new ProtoView(template, new DynamicProtoChangeDetector(null), new NativeShadowDomStrategy(null)) - .instantiate(null, null); + var view = pv.instantiate(null, null, reflector); view.hydrate(null, null, null); expect(view.nodes[0]).not.toBe(template); }); @@ -235,7 +235,7 @@ export function main() { new DynamicProtoChangeDetector(null), null); pv.bindElement(new ProtoElementInjector(null, 1, [SomeDirective])); - var view = pv.instantiate(null, null); + var view = pv.instantiate(null, null, reflector); view.hydrate(null, null, null); expect(view.elementInjectors.length).toBe(1); expect(view.elementInjectors[0].get(SomeDirective) instanceof SomeDirective).toBe(true); @@ -248,7 +248,7 @@ export function main() { pv.bindElement(protoParent); pv.bindElement(new ProtoElementInjector(protoParent, 1, [AnotherDirective])); - var view = pv.instantiate(null, null); + var view = pv.instantiate(null, null, reflector); view.hydrate(null, null, null); expect(view.elementInjectors.length).toBe(2); expect(view.elementInjectors[0].get(SomeDirective) instanceof SomeDirective).toBe(true); @@ -264,9 +264,9 @@ export function main() { pv.bindElement(testProtoElementInjector); var hostProtoInjector = new ProtoElementInjector(null, 0, []); - var hostInjector = hostProtoInjector.instantiate(null, null, null); + var hostInjector = hostProtoInjector.instantiate(null, null, null, reflector); var view; - expect(() => view = pv.instantiate(hostInjector, null)).not.toThrow(); + expect(() => view = pv.instantiate(hostInjector, null, reflector)).not.toThrow(); expect(testProtoElementInjector.parentElementInjector).toBe(view.elementInjectors[0]); expect(testProtoElementInjector.hostElementInjector).toBeNull(); }); @@ -279,8 +279,8 @@ export function main() { pv.bindElement(testProtoElementInjector); var hostProtoInjector = new ProtoElementInjector(null, 0, []); - var hostInjector = hostProtoInjector.instantiate(null, null, null); - expect(() => pv.instantiate(hostInjector, null)).not.toThrow(); + var hostInjector = hostProtoInjector.instantiate(null, null, null, reflector); + expect(() => pv.instantiate(hostInjector, null, reflector)).not.toThrow(); expect(testProtoElementInjector.parentElementInjector).toBeNull(); expect(testProtoElementInjector.hostElementInjector).toBe(hostInjector); }); @@ -295,7 +295,7 @@ export function main() { pv.bindElement(protoParent); pv.bindElement(new ProtoElementInjector(protoParent, 1, [AnotherDirective])); - var view = pv.instantiate(null, null); + var view = pv.instantiate(null, null, reflector); view.hydrate(null, null, null); expect(view.rootElementInjectors.length).toBe(1); expect(view.rootElementInjectors[0].get(SomeDirective) instanceof SomeDirective).toBe(true); @@ -307,7 +307,7 @@ export function main() { pv.bindElement(new ProtoElementInjector(null, 1, [SomeDirective])); pv.bindElement(new ProtoElementInjector(null, 2, [AnotherDirective])); - var view = pv.instantiate(null, null); + var view = pv.instantiate(null, null, reflector); view.hydrate(null, null, null); expect(view.rootElementInjectors.length).toBe(2) expect(view.rootElementInjectors[0].get(SomeDirective) instanceof SomeDirective).toBe(true); @@ -330,7 +330,7 @@ export function main() { function createNestedView(protoView) { ctx = new MyEvaluationContext(); - var view = protoView.instantiate(null, null); + var view = protoView.instantiate(null, null, reflector); view.hydrate(new Injector([]), null, ctx); return view; } @@ -622,7 +622,7 @@ export function main() { var rootProtoView = ProtoView.createRootProtoView(pv, element, someComponentDirective, new DynamicProtoChangeDetector(null), new NativeShadowDomStrategy(null)); - var view = rootProtoView.instantiate(null, null); + var view = rootProtoView.instantiate(null, null, reflector); view.hydrate(new Injector([]), null, null); expect(view.rootElementInjectors[0].get(SomeComponent)).not.toBe(null); }); @@ -631,7 +631,7 @@ export function main() { var rootProtoView = ProtoView.createRootProtoView(pv, element, someComponentDirective, new DynamicProtoChangeDetector(null), new NativeShadowDomStrategy(null)); - var view = rootProtoView.instantiate(null, null); + var view = rootProtoView.instantiate(null, null, reflector); view.hydrate(new Injector([]), null, null); expect(element.shadowRoot.childNodes[0].childNodes[0].nodeValue).toEqual('hi'); }); @@ -727,10 +727,11 @@ class TestProtoElementInjector extends ProtoElementInjector { super(parent, index, bindings, firstBindingIsComponent); } - instantiate(parent:ElementInjector, host:ElementInjector, events):ElementInjector { + instantiate(parent:ElementInjector, host:ElementInjector, events, + reflector: Reflector):ElementInjector { this.parentElementInjector = parent; this.hostElementInjector = host; - return super.instantiate(parent, host, events); + return super.instantiate(parent, host, events, reflector); } } diff --git a/modules/angular2/test/directives/foreach_spec.js b/modules/angular2/test/directives/foreach_spec.js index 4d37c660d3..1c7f9e05e6 100644 --- a/modules/angular2/test/directives/foreach_spec.js +++ b/modules/angular2/test/directives/foreach_spec.js @@ -44,7 +44,7 @@ export function main() { function createView(pv) { component = new TestComponent(); - view = pv.instantiate(null, null); + view = pv.instantiate(null, null, null); view.hydrate(new Injector([]), null, component); cd = view.changeDetector; } diff --git a/modules/angular2/test/directives/if_spec.js b/modules/angular2/test/directives/if_spec.js index 8c56515c28..f4880d02f9 100644 --- a/modules/angular2/test/directives/if_spec.js +++ b/modules/angular2/test/directives/if_spec.js @@ -44,7 +44,7 @@ export function main() { function createView(pv) { component = new TestComponent(); - view = pv.instantiate(null, null); + view = pv.instantiate(null, null, null); view.hydrate(new Injector([]), null, component); cd = view.changeDetector; } diff --git a/modules/angular2/test/directives/non_bindable_spec.js b/modules/angular2/test/directives/non_bindable_spec.js index f42ccf0184..0716542abd 100644 --- a/modules/angular2/test/directives/non_bindable_spec.js +++ b/modules/angular2/test/directives/non_bindable_spec.js @@ -42,7 +42,7 @@ export function main() { function createView(pv) { component = new TestComponent(); - view = pv.instantiate(null, null); + view = pv.instantiate(null, null, null); view.hydrate(new Injector([]), null, component); cd = view.changeDetector; } diff --git a/modules/angular2/test/directives/switch_spec.js b/modules/angular2/test/directives/switch_spec.js index e83a621f3c..b92e4197da 100644 --- a/modules/angular2/test/directives/switch_spec.js +++ b/modules/angular2/test/directives/switch_spec.js @@ -39,7 +39,7 @@ export function main() { function createView(pv) { component = new TestComponent(); - view = pv.instantiate(null, null); + view = pv.instantiate(null, null, null); view.hydrate(new Injector([]), null, component); cd = view.changeDetector; } diff --git a/modules/angular2/test/forms/integration_spec.js b/modules/angular2/test/forms/integration_spec.js index e5245963bd..5c8a0382eb 100644 --- a/modules/angular2/test/forms/integration_spec.js +++ b/modules/angular2/test/forms/integration_spec.js @@ -21,6 +21,8 @@ import {ControlGroupDirective, ControlDirective, Control, ControlGroup, Optional import * as validators from 'angular2/src/forms/validators'; +import {reflector} from 'angular2/src/reflection/reflection'; + export function main() { function detectChanges(view) { view.changeDetector.detectChanges(); @@ -48,7 +50,7 @@ export function main() { })); compiler.compile(componentType).then((pv) => { - var view = pv.instantiate(null, null); + var view = pv.instantiate(null, null, reflector); view.hydrate(new Injector([]), null, context); detectChanges(view); callback(view); diff --git a/modules/benchmarks/src/element_injector/element_injector_benchmark.js b/modules/benchmarks/src/element_injector/element_injector_benchmark.js index 8366ee7cc0..efabbfd420 100644 --- a/modules/benchmarks/src/element_injector/element_injector_benchmark.js +++ b/modules/benchmarks/src/element_injector/element_injector_benchmark.js @@ -33,11 +33,11 @@ export function main() { var bindings = [A, B, C]; var proto = new ProtoElementInjector(null, 0, bindings); - var elementInjector = proto.instantiate(null,null, null); + var elementInjector = proto.instantiate(null, null, null, null); function instantiate () { for (var i = 0; i < iterations; ++i) { - var ei = proto.instantiate(null, null, null); + var ei = proto.instantiate(null, null, null, null); ei.instantiateDirectives(appInjector, null, null); } } diff --git a/modules/benchmarks/src/naive_infinite_scroll/index.js b/modules/benchmarks/src/naive_infinite_scroll/index.js index 9f99139900..726bee0088 100644 --- a/modules/benchmarks/src/naive_infinite_scroll/index.js +++ b/modules/benchmarks/src/naive_infinite_scroll/index.js @@ -8,7 +8,7 @@ import {ExceptionHandler} from 'angular2/src/core/exception_handler'; import { bootstrap, Component, Viewport, Template, ViewContainer, Compiler, onChange } from 'angular2/angular2'; -import {reflector} from 'angular2/src/reflection/reflection'; +import {Reflector, reflector} from 'angular2/src/reflection/reflection'; import {CompilerCache} from 'angular2/src/core/compiler/compiler'; import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader'; import {ShadowDomStrategy, NativeShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy'; @@ -286,4 +286,10 @@ export function setupReflectorForAngular() { "parameters": [], "annotations": [] }); + + reflector.registerType(Reflector, { + "factory": () => reflector, + "parameters": [], + "annotations": [] + }); } diff --git a/modules/benchmarks/src/tree/tree_benchmark.js b/modules/benchmarks/src/tree/tree_benchmark.js index 3f7aaf0c48..dacfb47218 100644 --- a/modules/benchmarks/src/tree/tree_benchmark.js +++ b/modules/benchmarks/src/tree/tree_benchmark.js @@ -16,7 +16,7 @@ import {ComponentUrlMapper} from 'angular2/src/core/compiler/component_url_mappe import {StyleInliner} from 'angular2/src/core/compiler/style_inliner'; import {CssProcessor} from 'angular2/src/core/compiler/css_processor'; -import {reflector} from 'angular2/src/reflection/reflection'; +import {Reflector, reflector} from 'angular2/src/reflection/reflection'; import {DOM} from 'angular2/src/dom/dom_adapter'; import {isPresent} from 'angular2/src/facade/lang'; import {window, document, gc} from 'angular2/src/facade/browser'; @@ -177,6 +177,12 @@ function setupReflector() { "annotations": [] }); + reflector.registerType(Reflector, { + "factory": () => reflector, + "parameters": [], + "annotations": [] + }); + reflector.registerGetters({ 'value': (a) => a.value, 'left': (a) => a.left, diff --git a/modules/examples/src/hello_world/index_static.js b/modules/examples/src/hello_world/index_static.js index f2c2a22ab3..6973b0f393 100644 --- a/modules/examples/src/hello_world/index_static.js +++ b/modules/examples/src/hello_world/index_static.js @@ -18,7 +18,7 @@ import {ComponentUrlMapper} from 'angular2/src/core/compiler/component_url_mappe import {StyleInliner} from 'angular2/src/core/compiler/style_inliner'; import {CssProcessor} from 'angular2/src/core/compiler/css_processor'; -import {reflector} from 'angular2/src/reflection/reflection'; +import {Reflector, reflector} from 'angular2/src/reflection/reflection'; function setup() { reflector.registerType(app.HelloCmp, { @@ -156,6 +156,12 @@ function setup() { "annotations": [] }); + reflector.registerType(Reflector, { + "factory": () => reflector, + "parameters": [], + "annotations": [] + }); + reflector.registerGetters({ "greeting": (a) => a.greeting });