diff --git a/modules/angular2/src/change_detection/abstract_change_detector.ts b/modules/angular2/src/change_detection/abstract_change_detector.ts index 34a77d6093..e1216adea9 100644 --- a/modules/angular2/src/change_detection/abstract_change_detector.ts +++ b/modules/angular2/src/change_detection/abstract_change_detector.ts @@ -52,7 +52,7 @@ export class AbstractChangeDetector implements ChangeDetector { detectChangesInRecords(throwOnChange: boolean): void {} - hydrate(context: any, locals: Locals, directives: any): void {} + hydrate(context: any, locals: Locals, directives: any, pipes: any): void {} dehydrate(): void {} diff --git a/modules/angular2/src/change_detection/change_detection.ts b/modules/angular2/src/change_detection/change_detection.ts index 167caa1551..66b104374f 100644 --- a/modules/angular2/src/change_detection/change_detection.ts +++ b/modules/angular2/src/change_detection/change_detection.ts @@ -107,11 +107,10 @@ export class PreGeneratedChangeDetection extends ChangeDetection { _dynamicChangeDetection: ChangeDetection; _protoChangeDetectorFactories: StringMap; - constructor(private registry: PipeRegistry, - @Inject(PROTO_CHANGE_DETECTOR_KEY) @Optional() + constructor(@Inject(PROTO_CHANGE_DETECTOR_KEY) @Optional() protoChangeDetectorsForTest?: StringMap) { super(); - this._dynamicChangeDetection = new DynamicChangeDetection(registry); + this._dynamicChangeDetection = new DynamicChangeDetection(); this._protoChangeDetectorFactories = isPresent(protoChangeDetectorsForTest) ? protoChangeDetectorsForTest : preGeneratedProtoDetectors; @@ -122,8 +121,7 @@ export class PreGeneratedChangeDetection extends ChangeDetection { createProtoChangeDetector(definition: ChangeDetectorDefinition): ProtoChangeDetector { var id = definition.id; if (StringMapWrapper.contains(this._protoChangeDetectorFactories, id)) { - return StringMapWrapper.get(this._protoChangeDetectorFactories, id)(this.registry, - definition); + return StringMapWrapper.get(this._protoChangeDetectorFactories, id)(definition); } return this._dynamicChangeDetection.createProtoChangeDetector(definition); } @@ -139,10 +137,8 @@ export class PreGeneratedChangeDetection extends ChangeDetection { */ @Injectable() export class DynamicChangeDetection extends ChangeDetection { - constructor(private registry: PipeRegistry) { super(); } - createProtoChangeDetector(definition: ChangeDetectorDefinition): ProtoChangeDetector { - return new DynamicProtoChangeDetector(this.registry, definition); + return new DynamicProtoChangeDetector(definition); } } @@ -157,12 +153,10 @@ export class DynamicChangeDetection extends ChangeDetection { @Injectable() @CONST() export class JitChangeDetection extends ChangeDetection { - constructor(public registry: PipeRegistry) { super(); } - static isSupported(): boolean { return JitProtoChangeDetector.isSupported(); } createProtoChangeDetector(definition: ChangeDetectorDefinition): ProtoChangeDetector { - return new JitProtoChangeDetector(this.registry, definition); + return new JitProtoChangeDetector(definition); } } diff --git a/modules/angular2/src/change_detection/change_detection_jit_generator.ts b/modules/angular2/src/change_detection/change_detection_jit_generator.ts index e17d74ecaa..3adf32fb8a 100644 --- a/modules/angular2/src/change_detection/change_detection_jit_generator.ts +++ b/modules/angular2/src/change_detection/change_detection_jit_generator.ts @@ -67,14 +67,14 @@ export class ChangeDetectorJITGenerator { generate(): Function { var typeName = _sanitizeName(`ChangeDetector_${this.id}`); var classDefinition = ` - var ${typeName} = function ${typeName}(dispatcher, pipeRegistry, protos, directiveRecords) { + var ${typeName} = function ${typeName}(dispatcher, protos, directiveRecords) { ${ABSTRACT_CHANGE_DETECTOR}.call(this, ${JSON.stringify(this.id)}); ${DISPATCHER_ACCESSOR} = dispatcher; - ${PIPE_REGISTRY_ACCESSOR} = pipeRegistry; ${PROTOS_ACCESSOR} = protos; ${DIRECTIVES_ACCESSOR} = directiveRecords; ${LOCALS_ACCESSOR} = null; - ${CURRENT_PROTO} = null; + ${CURRENT_PROTO} = null; + ${PIPE_REGISTRY_ACCESSOR} = null; ${ALREADY_CHECKED_ACCESSOR} = false; ${this._genFieldDefinitions()} } @@ -91,32 +91,33 @@ export class ChangeDetectorJITGenerator { this.throwError(${CURRENT_PROTO}, e, e.stack); } } - + ${typeName}.prototype.__detectChangesInRecords = function(throwOnChange) { ${CURRENT_PROTO} = null; - + ${this._genLocalDefinitions()} ${this._genChangeDefinitions()} var ${IS_CHANGED_LOCAL} = false; var ${CHANGES_LOCAL} = null; - + context = ${CONTEXT_ACCESSOR}; - + ${this.records.map((r) => this._genRecord(r)).join("\n")} - + ${ALREADY_CHECKED_ACCESSOR} = true; } - + ${typeName}.prototype.callOnAllChangesDone = function() { ${this._genCallOnAllChangesDoneBody()} } - ${typeName}.prototype.hydrate = function(context, locals, directives) { + ${typeName}.prototype.hydrate = function(context, locals, directives, pipeRegistry) { ${MODE_ACCESSOR} = "${ChangeDetectionUtil.changeDetectionMode(this.changeDetectionStrategy)}"; ${CONTEXT_ACCESSOR} = context; ${LOCALS_ACCESSOR} = locals; ${this._genHydrateDirectives()} ${this._genHydrateDetectors()} + ${PIPE_REGISTRY_ACCESSOR} = pipeRegistry; ${ALREADY_CHECKED_ACCESSOR} = false; } @@ -124,14 +125,15 @@ export class ChangeDetectorJITGenerator { ${this._genPipeOnDestroy()} ${this._genFieldDefinitions()} ${LOCALS_ACCESSOR} = null; + ${PIPE_REGISTRY_ACCESSOR} = null; } ${typeName}.prototype.hydrated = function() { return ${CONTEXT_ACCESSOR} !== null; } - return function(dispatcher, pipeRegistry) { - return new ${typeName}(dispatcher, pipeRegistry, protos, directiveRecords); + return function(dispatcher) { + return new ${typeName}(dispatcher, protos, directiveRecords); } `; return new Function('AbstractChangeDetector', 'ChangeDetectionUtil', 'protos', diff --git a/modules/angular2/src/change_detection/dynamic_change_detector.ts b/modules/angular2/src/change_detection/dynamic_change_detector.ts index b44c5a96ba..c747a5faf8 100644 --- a/modules/angular2/src/change_detection/dynamic_change_detector.ts +++ b/modules/angular2/src/change_detection/dynamic_change_detector.ts @@ -18,10 +18,10 @@ export class DynamicChangeDetector extends AbstractChangeDetector { prevContexts: List; directives: any = null; alreadyChecked: boolean = false; + private pipeRegistry: PipeRegistry = null; constructor(id: string, private changeControlStrategy: string, private dispatcher: any, - private pipeRegistry: PipeRegistry, private protos: List, - private directiveRecords: List) { + private protos: List, private directiveRecords: List) { super(id); this.values = ListWrapper.createFixedSize(protos.length + 1); this.pipes = ListWrapper.createFixedSize(protos.length + 1); @@ -35,12 +35,13 @@ export class DynamicChangeDetector extends AbstractChangeDetector { ListWrapper.fill(this.changes, false); } - hydrate(context: any, locals: Locals, directives: any) { + hydrate(context: any, locals: Locals, directives: any, pipeRegistry: PipeRegistry): void { this.mode = ChangeDetectionUtil.changeDetectionMode(this.changeControlStrategy); this.values[0] = context; this.locals = locals; this.directives = directives; this.alreadyChecked = false; + this.pipeRegistry = pipeRegistry; } dehydrate() { @@ -51,6 +52,7 @@ export class DynamicChangeDetector extends AbstractChangeDetector { ListWrapper.fill(this.pipes, null); ListWrapper.fill(this.prevContexts, uninitialized); this.locals = null; + this.pipeRegistry = null; } _destroyPipes() { diff --git a/modules/angular2/src/change_detection/interfaces.ts b/modules/angular2/src/change_detection/interfaces.ts index d25a4880d5..117d620bc1 100644 --- a/modules/angular2/src/change_detection/interfaces.ts +++ b/modules/angular2/src/change_detection/interfaces.ts @@ -51,7 +51,7 @@ export interface ChangeDetector { removeChild(cd: ChangeDetector): void; removeShadowDomChild(cd: ChangeDetector): void; remove(): void; - hydrate(context: any, locals: Locals, directives: any): void; + hydrate(context: any, locals: Locals, directives: any, pipeRegistry: any): void; dehydrate(): void; markPathToRootAsCheckOnce(): void; diff --git a/modules/angular2/src/change_detection/jit_proto_change_detector.dart b/modules/angular2/src/change_detection/jit_proto_change_detector.dart index ccbd30eaeb..46a3251a5b 100644 --- a/modules/angular2/src/change_detection/jit_proto_change_detector.dart +++ b/modules/angular2/src/change_detection/jit_proto_change_detector.dart @@ -3,7 +3,7 @@ library change_detection.jit_proto_change_detector; import 'interfaces.dart' show ChangeDetector, ProtoChangeDetector; class JitProtoChangeDetector implements ProtoChangeDetector { - JitProtoChangeDetector(registry, definition) : super(); + JitProtoChangeDetector(definition) : super(); static bool isSupported() => false; diff --git a/modules/angular2/src/change_detection/jit_proto_change_detector.ts b/modules/angular2/src/change_detection/jit_proto_change_detector.ts index 4672e53139..7a28cb4c2d 100644 --- a/modules/angular2/src/change_detection/jit_proto_change_detector.ts +++ b/modules/angular2/src/change_detection/jit_proto_change_detector.ts @@ -9,15 +9,13 @@ import {ProtoRecordBuilder} from './proto_change_detector'; export class JitProtoChangeDetector implements ProtoChangeDetector { _factory: Function; - constructor(private _pipeRegistry, private definition: ChangeDetectorDefinition) { + constructor(private definition: ChangeDetectorDefinition) { this._factory = this._createFactory(definition); } static isSupported(): boolean { return true; } - instantiate(dispatcher: any): ChangeDetector { - return this._factory(dispatcher, this._pipeRegistry); - } + instantiate(dispatcher: any): ChangeDetector { return this._factory(dispatcher); } _createFactory(definition: ChangeDetectorDefinition) { var recordBuilder = new ProtoRecordBuilder(); diff --git a/modules/angular2/src/change_detection/pregen_proto_change_detector.dart b/modules/angular2/src/change_detection/pregen_proto_change_detector.dart index 51dac4b28f..48ab1ad497 100644 --- a/modules/angular2/src/change_detection/pregen_proto_change_detector.dart +++ b/modules/angular2/src/change_detection/pregen_proto_change_detector.dart @@ -3,7 +3,6 @@ library angular2.src.change_detection.pregen_proto_change_detector; import 'package:angular2/src/change_detection/coalesce.dart'; import 'package:angular2/src/change_detection/directive_record.dart'; import 'package:angular2/src/change_detection/interfaces.dart'; -import 'package:angular2/src/change_detection/pipes/pipe_registry.dart'; import 'package:angular2/src/change_detection/proto_change_detector.dart'; import 'package:angular2/src/change_detection/proto_record.dart'; @@ -25,10 +24,10 @@ export 'package:angular2/src/change_detection/change_detection_util.dart' export 'package:angular2/src/facade/lang.dart' show looseIdentical; typedef ProtoChangeDetector PregenProtoChangeDetectorFactory( - PipeRegistry registry, ChangeDetectorDefinition definition); + ChangeDetectorDefinition definition); typedef ChangeDetector InstantiateMethod(dynamic dispatcher, - PipeRegistry registry, List protoRecords, + List protoRecords, List directiveRecords); /// Implementation of [ProtoChangeDetector] for use by pre-generated change @@ -44,29 +43,28 @@ class PregenProtoChangeDetector extends ProtoChangeDetector { final InstantiateMethod _instantiateMethod; // [ChangeDetector] dependencies. - final PipeRegistry _pipeRegistry; final List _protoRecords; final List _directiveRecords; /// Internal ctor. PregenProtoChangeDetector._(this.id, this._instantiateMethod, - this._pipeRegistry, this._protoRecords, this._directiveRecords); + this._protoRecords, this._directiveRecords); static bool isSupported() => true; factory PregenProtoChangeDetector(InstantiateMethod instantiateMethod, - PipeRegistry registry, ChangeDetectorDefinition def) { + ChangeDetectorDefinition def) { // TODO(kegluneq): Pre-generate these (#2067). var recordBuilder = new ProtoRecordBuilder(); def.bindingRecords.forEach((b) { recordBuilder.add(b, def.variableNames); }); var protoRecords = coalesce(recordBuilder.records); - return new PregenProtoChangeDetector._(def.id, instantiateMethod, registry, + return new PregenProtoChangeDetector._(def.id, instantiateMethod, protoRecords, def.directiveRecords); } @override instantiate(dynamic dispatcher) => _instantiateMethod( - dispatcher, _pipeRegistry, _protoRecords, _directiveRecords); + dispatcher, _protoRecords, _directiveRecords); } diff --git a/modules/angular2/src/change_detection/proto_change_detector.ts b/modules/angular2/src/change_detection/proto_change_detector.ts index 4330a7fc42..4bb97bcce8 100644 --- a/modules/angular2/src/change_detection/proto_change_detector.ts +++ b/modules/angular2/src/change_detection/proto_change_detector.ts @@ -28,7 +28,6 @@ import { import {ChangeDetector, ProtoChangeDetector, ChangeDetectorDefinition} from './interfaces'; import {ChangeDetectionUtil} from './change_detection_util'; import {DynamicChangeDetector} from './dynamic_change_detector'; -import {PipeRegistry} from './pipes/pipe_registry'; import {BindingRecord} from './binding_record'; import {DirectiveRecord, DirectiveIndex} from './directive_record'; @@ -39,14 +38,13 @@ import {ProtoRecord, RecordType} from './proto_record'; export class DynamicProtoChangeDetector implements ProtoChangeDetector { _records: List; - constructor(private _pipeRegistry: PipeRegistry, private definition: ChangeDetectorDefinition) { + constructor(private definition: ChangeDetectorDefinition) { this._records = this._createRecords(definition); } instantiate(dispatcher: any): ChangeDetector { return new DynamicChangeDetector(this.definition.id, this.definition.strategy, dispatcher, - this._pipeRegistry, this._records, - this.definition.directiveRecords); + this._records, this.definition.directiveRecords); } _createRecords(definition: ChangeDetectorDefinition) { diff --git a/modules/angular2/src/core/compiler/element_injector.ts b/modules/angular2/src/core/compiler/element_injector.ts index c503e31aba..618de50ada 100644 --- a/modules/angular2/src/core/compiler/element_injector.ts +++ b/modules/angular2/src/core/compiler/element_injector.ts @@ -54,27 +54,29 @@ import { onAllChangesDone } from 'angular2/src/core/annotations_impl/annotations'; import {hasLifecycleHook} from './directive_lifecycle_reflector'; -import {ChangeDetector, ChangeDetectorRef} from 'angular2/change_detection'; +import {ChangeDetector, ChangeDetectorRef, PipeRegistry} from 'angular2/change_detection'; import {QueryList} from './query_list'; import {reflector} from 'angular2/src/reflection/reflection'; import {DirectiveMetadata} from 'angular2/src/render/api'; var _staticKeys; -class StaticKeys { +export class StaticKeys { viewManagerId: number; protoViewId: number; viewContainerId: number; changeDetectorRefId: number; elementRefId: number; + pipeRegistryKey: Key; constructor() { - // TODO: vsavkin Key.annotate(Key.get(AppView), 'static') this.viewManagerId = Key.get(avmModule.AppViewManager).id; this.protoViewId = Key.get(ProtoViewRef).id; this.viewContainerId = Key.get(ViewContainerRef).id; this.changeDetectorRefId = Key.get(ChangeDetectorRef).id; this.elementRefId = Key.get(ElementRef).id; + // not an id because the public API of injector works only with keys and tokens + this.pipeRegistryKey = Key.get(PipeRegistry); } static instance(): StaticKeys { @@ -529,14 +531,15 @@ export class ElementInjector extends TreeNode implements Depend // |boundary // | // this._injector - var parent = this._getParentInjector(imperativelyCreatedInjector, host); + var parent = this._closestBoundaryInjector(imperativelyCreatedInjector, host); this._reattachInjector(this._injector, parent, true); } } - private _getParentInjector(injector: Injector, host: ElementInjector): Injector { - if (isPresent(injector)) { - return injector; + private _closestBoundaryInjector(imperativelyCreatedInjector: Injector, + host: ElementInjector): Injector { + if (isPresent(imperativelyCreatedInjector)) { + return imperativelyCreatedInjector; } else if (isPresent(host)) { return host._injector; } else { @@ -549,6 +552,11 @@ export class ElementInjector extends TreeNode implements Depend injector.internalStrategy.hydrate(); } + getPipeRegistry(): PipeRegistry { + var pipeRegistryKey = StaticKeys.instance().pipeRegistryKey; + return this._injector.getOptional(pipeRegistryKey); + } + hasVariableBinding(name: string): boolean { var vb = this._proto.directiveVariableBindings; return isPresent(vb) && vb.has(name); diff --git a/modules/angular2/src/core/compiler/view_manager_utils.ts b/modules/angular2/src/core/compiler/view_manager_utils.ts index 464c51da2c..0bbfba6e3f 100644 --- a/modules/angular2/src/core/compiler/view_manager_utils.ts +++ b/modules/angular2/src/core/compiler/view_manager_utils.ts @@ -141,12 +141,11 @@ export class AppViewManagerUtils { var elementInjector = contextView.elementInjectors[contextBoundElementIndex]; var injector = isPresent(bindings) ? Injector.fromResolvedBindings(bindings) : null; - this._hydrateView(view, injector, elementInjector.getHost(), contextView.context, contextView.locals); } - _hydrateView(view: viewModule.AppView, injector: Injector, + _hydrateView(view: viewModule.AppView, imperativelyCreatedInjector: Injector, hostElementInjector: eli.ElementInjector, context: Object, parentLocals: Locals) { view.context = context; view.locals.parent = parentLocals; @@ -156,13 +155,24 @@ export class AppViewManagerUtils { var elementInjector = view.elementInjectors[i]; if (isPresent(elementInjector)) { - elementInjector.hydrate(injector, hostElementInjector, view.preBuiltObjects[i]); + elementInjector.hydrate(imperativelyCreatedInjector, hostElementInjector, + view.preBuiltObjects[i]); this._populateViewLocals(view, elementInjector); this._setUpEventEmitters(view, elementInjector, i); this._setUpHostActions(view, elementInjector, i); } } - view.changeDetector.hydrate(view.context, view.locals, view); + var pipeRegistry = this._getPipeRegistry(imperativelyCreatedInjector, hostElementInjector); + view.changeDetector.hydrate(view.context, view.locals, view, pipeRegistry); + } + + _getPipeRegistry(imperativelyCreatedInjector: Injector, + hostElementInjector: eli.ElementInjector) { + var pipeRegistryKey = eli.StaticKeys.instance().pipeRegistryKey; + if (isPresent(imperativelyCreatedInjector)) + return imperativelyCreatedInjector.getOptional(pipeRegistryKey); + if (isPresent(hostElementInjector)) return hostElementInjector.getPipeRegistry(); + return null; } _populateViewLocals(view: viewModule.AppView, elementInjector: eli.ElementInjector): void { diff --git a/modules/angular2/src/transform/template_compiler/change_detector_codegen.dart b/modules/angular2/src/transform/template_compiler/change_detector_codegen.dart index 7116af55f8..c548bb2c53 100644 --- a/modules/angular2/src/transform/template_compiler/change_detector_codegen.dart +++ b/modules/angular2/src/transform/template_compiler/change_detector_codegen.dart @@ -125,7 +125,7 @@ class _CodegenState { buf.write(''' class $_changeDetectorTypeName extends $_BASE_CLASS { final dynamic $_DISPATCHER_ACCESSOR; - final $_GEN_PREFIX.PipeRegistry $_PIPE_REGISTRY_ACCESSOR; + $_GEN_PREFIX.PipeRegistry $_PIPE_REGISTRY_ACCESSOR; final $_GEN_PREFIX.List<$_GEN_PREFIX.ProtoRecord> $_PROTOS_ACCESSOR; final $_GEN_PREFIX.List<$_GEN_PREFIX.DirectiveRecord> $_DIRECTIVES_ACCESSOR; @@ -141,7 +141,6 @@ class _CodegenState { $_changeDetectorTypeName( this.$_DISPATCHER_ACCESSOR, - this.$_PIPE_REGISTRY_ACCESSOR, this.$_PROTOS_ACCESSOR, this.$_DIRECTIVES_ACCESSOR) : super(${JSON.encode(_changeDetectorDefId)}); @@ -155,7 +154,7 @@ class _CodegenState { this.throwError($_CURRENT_PROTO, e, s); } } - + void __detectChangesInRecords(throwOnChange) { ${_genLocalDefinitions()} ${_genChangeDefinitons()} @@ -168,18 +167,19 @@ class _CodegenState { $_ALREADY_CHECKED_ACCESSOR = true; } - + void callOnAllChangesDone() { ${_getCallOnAllChangesDoneBody()} } - void hydrate($_contextTypeName context, locals, directives) { + void hydrate($_contextTypeName context, locals, directives, pipeRegistry) { $_MODE_ACCESSOR = '$_changeDetectionMode'; $_CONTEXT_ACCESSOR = context; $_LOCALS_ACCESSOR = locals; ${_genHydrateDirectives()} ${_genHydrateDetectors()} $_ALREADY_CHECKED_ACCESSOR = false; + $_PIPE_REGISTRY_ACCESSOR = pipeRegistry; } void dehydrate() { @@ -190,17 +190,17 @@ class _CodegenState { : '$f = $_UTIL.uninitialized();'; }).join('')} $_LOCALS_ACCESSOR = null; + $_PIPE_REGISTRY_ACCESSOR = null; } hydrated() => $_CONTEXT_ACCESSOR != null; static $_GEN_PREFIX.ProtoChangeDetector $PROTO_CHANGE_DETECTOR_FACTORY_METHOD( - $_GEN_PREFIX.PipeRegistry registry, $_GEN_PREFIX.ChangeDetectorDefinition def) { return new $_GEN_PREFIX.PregenProtoChangeDetector( - (a, b, c, d) => new $_changeDetectorTypeName(a, b, c, d), - registry, def); + (a, b, c) => new $_changeDetectorTypeName(a, b, c), + def); } } '''); diff --git a/modules/angular2/test/change_detection/change_detection_spec.ts b/modules/angular2/test/change_detection/change_detection_spec.ts index 809a700881..c11095fad0 100644 --- a/modules/angular2/test/change_detection/change_detection_spec.ts +++ b/modules/angular2/test/change_detection/change_detection_spec.ts @@ -27,14 +27,14 @@ export function main() { }); it("should return a proto change detector when one is available", () => { - var map = {'id': (registry, def) => proto}; - var cd = new PreGeneratedChangeDetection(null, map); + var map = {'id': (def) => proto}; + var cd = new PreGeneratedChangeDetection(map); expect(cd.createProtoChangeDetector(def)).toBe(proto) }); it("should delegate to dynamic change detection otherwise", () => { - var cd = new PreGeneratedChangeDetection(null, {}); + var cd = new PreGeneratedChangeDetection({}); expect(cd.createProtoChangeDetector(def)).toBeAnInstanceOf(DynamicProtoChangeDetector); }); }); diff --git a/modules/angular2/test/change_detection/change_detector_spec.ts b/modules/angular2/test/change_detection/change_detector_spec.ts index eb319f68ce..1be0ccaa0e 100644 --- a/modules/angular2/test/change_detection/change_detector_spec.ts +++ b/modules/angular2/test/change_detection/change_detector_spec.ts @@ -66,20 +66,19 @@ const _DEFAULT_CONTEXT = CONST_EXPR(new Object()); */ export function main() { ListWrapper.forEach(['dynamic', 'JIT', 'Pregen'], (cdType) => { - if (cdType == "JIT" && IS_DARTIUM) return; if (cdType == "Pregen" && !IS_DARTIUM) return; describe(`${cdType} Change Detector`, () => { - function _getProtoChangeDetector(def: ChangeDetectorDefinition, registry = null) { + function _getProtoChangeDetector(def: ChangeDetectorDefinition) { switch (cdType) { case 'dynamic': - return new DynamicProtoChangeDetector(registry, def); + return new DynamicProtoChangeDetector(def); case 'JIT': - return new JitProtoChangeDetector(registry, def); + return new JitProtoChangeDetector(def); case 'Pregen': - return getFactoryById(def.id)(registry, def); + return getFactoryById(def.id)(def); default: return null; } @@ -87,9 +86,7 @@ export function main() { function _createWithoutHydrate(expression: string) { var dispatcher = new TestDispatcher(); - var registry = null; - var cd = _getProtoChangeDetector(getDefinition(expression).cdDef, registry) - .instantiate(dispatcher); + var cd = _getProtoChangeDetector(getDefinition(expression).cdDef).instantiate(dispatcher); return new _ChangeDetectorAndDispatcher(cd, dispatcher); } @@ -98,9 +95,9 @@ export function main() { registry = null) { var dispatcher = new TestDispatcher(); var testDef = getDefinition(expression); - var protoCd = _getProtoChangeDetector(testDef.cdDef, registry); + var protoCd = _getProtoChangeDetector(testDef.cdDef); var cd = protoCd.instantiate(dispatcher); - cd.hydrate(context, testDef.locals, null); + cd.hydrate(context, testDef.locals, null, registry); return new _ChangeDetectorAndDispatcher(cd, dispatcher); } @@ -298,7 +295,7 @@ export function main() { it('should support interpolation', () => { var val = _createChangeDetector('interpolation', new TestData('value')); - val.changeDetector.hydrate(new TestData('value'), null, null); + val.changeDetector.hydrate(new TestData('value'), null, null, null); val.changeDetector.detectChanges(); @@ -361,8 +358,8 @@ export function main() { it('should happen directly, without invoking the dispatcher', () => { var val = _createWithoutHydrate('directNoDispatcher'); - val.changeDetector.hydrate(_DEFAULT_CONTEXT, null, - new FakeDirectives([directive1], [])); + val.changeDetector.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directive1], []), + null); val.changeDetector.detectChanges(); expect(val.dispatcher.loggedValues).toEqual([]); expect(directive1.a).toEqual(42); @@ -371,7 +368,8 @@ export function main() { describe('onChange', () => { it('should notify the directive when a group of records changes', () => { var cd = _createWithoutHydrate('groupChanges').changeDetector; - cd.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directive1, directive2], [])); + cd.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directive1, directive2], []), + null); cd.detectChanges(); expect(directive1.changes).toEqual({'a': 1, 'b': 2}); expect(directive2.changes).toEqual({'a': 3}); @@ -382,7 +380,7 @@ export function main() { it('should notify the directive when it is checked', () => { var cd = _createWithoutHydrate('directiveOnCheck').changeDetector; - cd.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directive1], [])); + cd.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directive1], []), null); cd.detectChanges(); expect(directive1.onCheckCalled).toBe(true); @@ -395,7 +393,7 @@ export function main() { it('should not call onCheck in detectNoChanges', () => { var cd = _createWithoutHydrate('directiveOnCheck').changeDetector; - cd.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directive1], [])); + cd.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directive1], []), null); cd.checkNoChanges(); @@ -407,7 +405,7 @@ export function main() { it('should notify the directive after it has been checked the first time', () => { var cd = _createWithoutHydrate('directiveOnInit').changeDetector; - cd.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directive1], [])); + cd.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directive1], []), null); cd.detectChanges(); @@ -423,7 +421,7 @@ export function main() { it('should not call onInit in detectNoChanges', () => { var cd = _createWithoutHydrate('directiveOnInit').changeDetector; - cd.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directive1], [])); + cd.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directive1], []), null); cd.checkNoChanges(); @@ -434,7 +432,8 @@ export function main() { describe('onAllChangesDone', () => { it('should be called after processing all the children', () => { var cd = _createWithoutHydrate('emptyWithDirectiveRecords').changeDetector; - cd.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directive1, directive2], [])); + cd.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directive1, directive2], []), + null); cd.detectChanges(); @@ -462,7 +461,7 @@ export function main() { it('should not be called when onAllChangesDone is false', () => { var cd = _createWithoutHydrate('noCallbacks').changeDetector; - cd.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directive1], [])); + cd.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directive1], []), null); cd.detectChanges(); @@ -478,7 +477,7 @@ export function main() { td1 = new TestDirective(() => onChangesDoneCalls.push(td1)); var td2; td2 = new TestDirective(() => onChangesDoneCalls.push(td2)); - cd.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([td1, td2], [])); + cd.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([td1, td2], []), null); cd.detectChanges(); @@ -499,8 +498,10 @@ export function main() { parentDirective = new TestDirective(() => { orderOfOperations.push(parentDirective); }); - parent.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([parentDirective], [])); - child.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directiveInShadowDom], [])); + parent.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([parentDirective], []), + null); + child.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directiveInShadowDom], []), + null); parent.detectChanges(); expect(orderOfOperations).toEqual([parentDirective, directiveInShadowDom]); @@ -515,7 +516,8 @@ export function main() { directive.a = 'aaa'; var val = _createWithoutHydrate('readingDirectives'); - val.changeDetector.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directive], [])); + val.changeDetector.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directive], []), + null); val.changeDetector.detectChanges(); @@ -625,13 +627,13 @@ export function main() { var cd = _createWithoutHydrate('emptyUsingDefaultStrategy').changeDetector; expect(cd.mode).toEqual(null); - cd.hydrate(_DEFAULT_CONTEXT, null, null); + cd.hydrate(_DEFAULT_CONTEXT, null, null, null); expect(cd.mode).toEqual(CHECK_ALWAYS); }); it('should set the mode to CHECK_ONCE when the push change detection is used', () => { var cd = _createWithoutHydrate('emptyUsingOnPushStrategy').changeDetector; - cd.hydrate(_DEFAULT_CONTEXT, null, null); + cd.hydrate(_DEFAULT_CONTEXT, null, null, null); expect(cd.mode).toEqual(CHECK_ONCE); }); @@ -639,7 +641,7 @@ export function main() { it('should not check a detached change detector', () => { var val = _createChangeDetector('a', new TestData('value')); - val.changeDetector.hydrate(_DEFAULT_CONTEXT, null, null); + val.changeDetector.hydrate(_DEFAULT_CONTEXT, null, null, null); val.changeDetector.mode = DETACHED; val.changeDetector.detectChanges(); @@ -649,7 +651,7 @@ export function main() { it('should not check a checked change detector', () => { var val = _createChangeDetector('a', new TestData('value')); - val.changeDetector.hydrate(_DEFAULT_CONTEXT, null, null); + val.changeDetector.hydrate(_DEFAULT_CONTEXT, null, null, null); val.changeDetector.mode = CHECKED; val.changeDetector.detectChanges(); @@ -658,7 +660,7 @@ export function main() { it('should change CHECK_ONCE to CHECKED', () => { var cd = _createChangeDetector('10').changeDetector; - cd.hydrate(_DEFAULT_CONTEXT, null, null); + cd.hydrate(_DEFAULT_CONTEXT, null, null, null); cd.mode = CHECK_ONCE; cd.detectChanges(); @@ -668,7 +670,7 @@ export function main() { it('should not change the CHECK_ALWAYS', () => { var cd = _createChangeDetector('10').changeDetector; - cd.hydrate(_DEFAULT_CONTEXT, null, null); + cd.hydrate(_DEFAULT_CONTEXT, null, null, null); cd.mode = CHECK_ALWAYS; cd.detectChanges(); @@ -682,7 +684,7 @@ export function main() { beforeEach(() => { checkedDetector = _createWithoutHydrate('emptyUsingOnPushStrategy').changeDetector; - checkedDetector.hydrate(_DEFAULT_CONTEXT, null, null); + checkedDetector.hydrate(_DEFAULT_CONTEXT, null, null, null); checkedDetector.mode = CHECKED; var targetDirective = new TestData(null); @@ -691,7 +693,7 @@ export function main() { it('should set the mode to CHECK_ONCE when a binding is updated', () => { var cd = _createWithoutHydrate('onPushRecordsUsingDefaultStrategy').changeDetector; - cd.hydrate(_DEFAULT_CONTEXT, null, directives); + cd.hydrate(_DEFAULT_CONTEXT, null, directives, null); expect(checkedDetector.mode).toEqual(CHECKED); @@ -735,13 +737,13 @@ export function main() { it('should be able to rehydrate a change detector', () => { var cd = _createChangeDetector('name').changeDetector; - cd.hydrate('some context', null, null); + cd.hydrate('some context', null, null, null); expect(cd.hydrated()).toBe(true); cd.dehydrate(); expect(cd.hydrated()).toBe(false); - cd.hydrate('other context', null, null); + cd.hydrate('other context', null, null, null); expect(cd.hydrated()).toBe(true); }); diff --git a/modules/angular2/test/core/compiler/element_injector_spec.ts b/modules/angular2/test/core/compiler/element_injector_spec.ts index 27435b42e6..566ff892ae 100644 --- a/modules/angular2/test/core/compiler/element_injector_spec.ts +++ b/modules/angular2/test/core/compiler/element_injector_spec.ts @@ -242,7 +242,7 @@ class TestNode extends TreeNode { export function main() { var defaultPreBuiltObjects = new PreBuiltObjects(null, new DummyView(1), null); - + // An injector with more than 10 bindings will switch to the dynamic strategy var dynamicBindings = []; @@ -562,7 +562,7 @@ export function main() { var extraBindings = context['bindings']; describe(`${context['strategy']} strategy`, () => { - + describe("hydrate", () => { it("should instantiate directives that have no dependencies", () => { var bindings = ListWrapper.concat([SimpleDirective], extraBindings); @@ -610,15 +610,15 @@ export function main() { (val) => `${val}-injectable2`, ['injectable1']) ]; - + var inj = injector(ListWrapper.concat( - [DirectiveBinding.createFromType(SimpleDirective, + [DirectiveBinding.createFromType(SimpleDirective, new dirAnn.Directive({hostInjector: hostInjector}))], extraBindings)); - + expect(inj.get('injectable2')).toEqual('injectable1-injectable2'); }); - + it("should instantiate viewInjector injectables that have dependencies", () => { var viewInjector = [ bind('injectable1') @@ -628,15 +628,15 @@ export function main() { (val) => `${val}-injectable2`, ['injectable1']) ]; - - + + var inj = injector(ListWrapper.concat( [DirectiveBinding.createFromType(SimpleDirective, new dirAnn.Component({ - viewInjector: viewInjector}))], extraBindings), + viewInjector: viewInjector}))], extraBindings), null, true); expect(inj.get('injectable2')).toEqual('injectable1-injectable2'); }); - + it("should instantiate components that depend on viewInjector bindings", () => { var inj = injector( ListWrapper.concat([DirectiveBinding.createFromType(NeedsService, new dirAnn.Component({ @@ -658,7 +658,7 @@ export function main() { .toThrowError(containsRegexp( `No provider for service! (${stringify(NeedsService) } -> service)`)); }); - + it("should instantiate directives that depend on hostInjector bindings of other directives", () => { var shadowInj = hostShadowInjectors( ListWrapper.concat([DirectiveBinding.createFromType(SimpleDirective, new dirAnn.Component({ @@ -668,7 +668,7 @@ export function main() { ); expect(shadowInj.get(NeedsService).service).toEqual('hostService'); }); - + it("should instantiate directives that depend on imperativley created injector bindings", () => { var imperativelyCreatedInjector = Injector.resolveAndCreate([ bind("service").toValue('appService') @@ -899,7 +899,7 @@ export function main() { }); it('should inject ChangeDetectorRef', () => { - var cd = new DynamicChangeDetector(null, null, null, null, [], []); + var cd = new DynamicChangeDetector(null, null, null, [], []); var view = new DummyView(); var childView = new DummyView(); childView.changeDetector = cd; diff --git a/modules/angular2/test/core/compiler/integration_spec.ts b/modules/angular2/test/core/compiler/integration_spec.ts index 5638fd7098..76e68de5f4 100644 --- a/modules/angular2/test/core/compiler/integration_spec.ts +++ b/modules/angular2/test/core/compiler/integration_spec.ts @@ -219,24 +219,15 @@ export function main() { })); describe('pipes', () => { - beforeEachBindings(() => { - return [ - bind(ChangeDetection) - .toFactory(() => new DynamicChangeDetection( - new PipeRegistry({"double": [new DoublePipeFactory()]})), - []) - ]; - }); - it("should support pipes in bindings", inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { - tcb.overrideView(MyComp, new viewAnn.View({ + tcb.overrideView(MyCompWithPipes, new viewAnn.View({ template: '
', directives: [MyDir] })) - .createAsync(MyComp) + .createAsync(MyCompWithPipes) .then((rootTC) => { rootTC.componentInstance.ctxProp = 'a'; rootTC.detectChanges(); @@ -1410,6 +1401,21 @@ class PushCmpWithRef { propagate() { this.ref.requestCheck(); } } +@Injectable() +class PipeRegistryWithDouble extends PipeRegistry { + constructor() { super({"double": [new DoublePipeFactory()]}); } +} + +@Component({ + selector: 'my-comp-with-pipes', + viewInjector: [new Binding(PipeRegistry, {toClass: PipeRegistryWithDouble})] +}) +@View({directives: []}) +@Injectable() +class MyCompWithPipes { + ctxProp: string = "initial value"; +} + @Component({selector: 'my-comp'}) @View({directives: []}) @Injectable() @@ -1424,13 +1430,6 @@ class MyComp { } } -@Component({selector: 'component-with-pipes', properties: ["prop"]}) -@View({template: ''}) -@Injectable() -class ComponentWithPipes { - prop: string; -} - @Component({selector: 'child-cmp', properties: ['dirProp'], viewInjector: [MyService]}) @View({directives: [MyDir], template: '{{ctxProp}}'}) @Injectable() diff --git a/modules/angular2/test/transform/integration/two_annotations_files/expected/bar.ng_deps.dart b/modules/angular2/test/transform/integration/two_annotations_files/expected/bar.ng_deps.dart index 5279e94385..20de23d140 100644 --- a/modules/angular2/test/transform/integration/two_annotations_files/expected/bar.ng_deps.dart +++ b/modules/angular2/test/transform/integration/two_annotations_files/expected/bar.ng_deps.dart @@ -27,7 +27,7 @@ void initReflector(reflector) { } class _MyComponent_ChangeDetector0 extends _gen.AbstractChangeDetector { final dynamic _dispatcher; - final _gen.PipeRegistry _pipeRegistry; + _gen.PipeRegistry _pipeRegistry; final _gen.List<_gen.ProtoRecord> _protos; final _gen.List<_gen.DirectiveRecord> _directiveRecords; dynamic _locals = null; @@ -37,8 +37,8 @@ class _MyComponent_ChangeDetector0 extends _gen.AbstractChangeDetector { dynamic _myNum0 = _gen.ChangeDetectionUtil.uninitialized(); dynamic _interpolate1 = _gen.ChangeDetectionUtil.uninitialized(); - _MyComponent_ChangeDetector0(this._dispatcher, this._pipeRegistry, - this._protos, this._directiveRecords) + _MyComponent_ChangeDetector0( + this._dispatcher, this._protos, this._directiveRecords) : super("MyComponent_comp_0"); void detectChangesInRecords(throwOnChange) { @@ -100,12 +100,13 @@ class _MyComponent_ChangeDetector0 extends _gen.AbstractChangeDetector { _dispatcher.notifyOnAllChangesDone(); } - void hydrate(MyComponent context, locals, directives) { + void hydrate(MyComponent context, locals, directives, pipeRegistry) { mode = 'ALWAYS_CHECK'; _context = context; _locals = locals; _alreadyChecked = false; + _pipeRegistry = pipeRegistry; } void dehydrate() { @@ -113,14 +114,14 @@ class _MyComponent_ChangeDetector0 extends _gen.AbstractChangeDetector { _myNum0 = _gen.ChangeDetectionUtil.uninitialized(); _interpolate1 = _gen.ChangeDetectionUtil.uninitialized(); _locals = null; + _pipeRegistry = null; } hydrated() => _context != null; static _gen.ProtoChangeDetector newProtoChangeDetector( - _gen.PipeRegistry registry, _gen.ChangeDetectorDefinition def) { + _gen.ChangeDetectorDefinition def) { return new _gen.PregenProtoChangeDetector( - (a, b, c, d) => new _MyComponent_ChangeDetector0(a, b, c, d), registry, - def); + (a, b, c) => new _MyComponent_ChangeDetector0(a, b, c), def); } } diff --git a/modules/angular2/tsconfig.json b/modules/angular2/tsconfig.json index 13249a24e7..54a0674148 100644 --- a/modules/angular2/tsconfig.json +++ b/modules/angular2/tsconfig.json @@ -1,6 +1,7 @@ { "compilerOptions": { "emitDecoratorMetadata": true, + "experimentalDecorators": true, "declaration": true, "module": "commonjs", "rootDir": ".", diff --git a/modules/benchmarks/src/change_detection/change_detection_benchmark.ts b/modules/benchmarks/src/change_detection/change_detection_benchmark.ts index a2ed516439..7fc0b590b0 100644 --- a/modules/benchmarks/src/change_detection/change_detection_benchmark.ts +++ b/modules/benchmarks/src/change_detection/change_detection_benchmark.ts @@ -280,10 +280,10 @@ function setUpChangeDetection(changeDetection: ChangeDetection, iterations, obje new ChangeDetectorDefinition("proto", null, [], bindings, [directiveRecord])); var targetObj = new Obj(); - parentCd.hydrate(object, null, new FakeDirectives(targetObj)); + parentCd.hydrate(object, null, new FakeDirectives(targetObj), null); for (var i = 0; i < iterations; ++i) { var cd = proto.instantiate(dispatcher); - cd.hydrate(object, null, new FakeDirectives(targetObj)); + cd.hydrate(object, null, new FakeDirectives(targetObj), null); parentCd.addChild(cd); } return parentCd; @@ -332,7 +332,7 @@ export function main() { // -- DYNAMIC var ng2DynamicChangeDetector = - setUpChangeDetection(new DynamicChangeDetection(null), numberOfDetectors, object); + setUpChangeDetection(new DynamicChangeDetection(), numberOfDetectors, object); runChangeDetectionReads(ng2DynamicChangeDetector, 1); // warmup @@ -352,7 +352,7 @@ export function main() { // Reenable when we have transformers for Dart if (isJsObject({})) { var ng2JitChangeDetector = - setUpChangeDetection(new JitChangeDetection(null), numberOfDetectors, object); + setUpChangeDetection(new JitChangeDetection(), numberOfDetectors, object); runChangeDetectionReads(ng2JitChangeDetector, 1); // warmup diff --git a/modules/benchmarks/src/compiler/compiler_benchmark.ts b/modules/benchmarks/src/compiler/compiler_benchmark.ts index fa56250b0e..02e476b4d0 100644 --- a/modules/benchmarks/src/compiler/compiler_benchmark.ts +++ b/modules/benchmarks/src/compiler/compiler_benchmark.ts @@ -39,9 +39,9 @@ export function main() { var shadowDomStrategy = new NativeShadowDomStrategy(); var renderCompiler = new rc.DefaultDomCompiler(new Parser(new Lexer()), shadowDomStrategy, new ViewLoader(null, null, null)); - var compiler = new Compiler( - reader, cache, viewResolver, new ComponentUrlMapper(), urlResolver, renderCompiler, - new ProtoViewFactory(new DynamicChangeDetection(null)), new FakeAppRootUrl()); + var compiler = new Compiler(reader, cache, viewResolver, new ComponentUrlMapper(), urlResolver, + renderCompiler, new ProtoViewFactory(new DynamicChangeDetection()), + new FakeAppRootUrl()); function measureWrapper(func, desc) { return function() {