refactor(view): moved the logic from ProtoView to ProtoViewFactory
This commit is contained in:
		
							parent
							
								
									0f4a089c32
								
							
						
					
					
						commit
						ce6a2ba836
					
				| @ -4,9 +4,13 @@ import {IterableChangesFactory} from './pipes/iterable_changes'; | ||||
| import {KeyValueChangesFactory} from './pipes/keyvalue_changes'; | ||||
| import {AsyncPipeFactory} from './pipes/async_pipe'; | ||||
| import {NullPipeFactory} from './pipes/null_pipe'; | ||||
| import {BindingRecord} from './binding_record'; | ||||
| import {DirectiveRecord} from './directive_record'; | ||||
| import {DEFAULT} from './constants'; | ||||
| import {ChangeDetection, ProtoChangeDetector} from './interfaces'; | ||||
| import {Injectable} from 'angular2/di'; | ||||
| import {List} from 'angular2/src/facade/collection'; | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * Structural diffing for `Object`s and `Map`s. | ||||
| @ -61,8 +65,9 @@ export class DynamicChangeDetection extends ChangeDetection { | ||||
|     this.registry = registry; | ||||
|   } | ||||
| 
 | ||||
|   createProtoChangeDetector(name:string, changeControlStrategy:string = DEFAULT):ProtoChangeDetector{ | ||||
|     return new DynamicProtoChangeDetector(this.registry, changeControlStrategy); | ||||
|   createProtoChangeDetector(name:string, bindingRecords:List<BindingRecord>, variableBindings:List<string>, | ||||
|                             directiveRecords:List<DirectiveRecord>, changeControlStrategy:string = DEFAULT):ProtoChangeDetector{ | ||||
|     return new DynamicProtoChangeDetector(this.registry, bindingRecords, variableBindings, directiveRecords, changeControlStrategy); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| @ -82,8 +87,9 @@ export class JitChangeDetection extends ChangeDetection { | ||||
|     this.registry = registry; | ||||
|   } | ||||
| 
 | ||||
|   createProtoChangeDetector(name:string, changeControlStrategy:string = DEFAULT):ProtoChangeDetector{ | ||||
|     return new JitProtoChangeDetector(this.registry, changeControlStrategy); | ||||
|   createProtoChangeDetector(name:string, bindingRecords:List<BindingRecord>, variableBindings:List<string>, | ||||
|                             directiveRecords:List<DirectiveRecord>, changeControlStrategy:string = DEFAULT):ProtoChangeDetector{ | ||||
|     return new JitProtoChangeDetector(this.registry, bindingRecords, variableBindings, directiveRecords, changeControlStrategy); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -4,7 +4,7 @@ import {DEFAULT} from './constants'; | ||||
| import {BindingRecord} from './binding_record'; | ||||
| 
 | ||||
| export class ProtoChangeDetector  { | ||||
|   instantiate(dispatcher:any, bindingRecords:List, variableBindings:List, directiveRecords:List):ChangeDetector{ | ||||
|   instantiate(dispatcher:any):ChangeDetector{ | ||||
|     return null; | ||||
|   } | ||||
| } | ||||
| @ -33,7 +33,8 @@ export class ProtoChangeDetector  { | ||||
|  * @exportedAs angular2/change_detection | ||||
|  */ | ||||
| export class ChangeDetection { | ||||
|   createProtoChangeDetector(name:string, changeControlStrategy:string=DEFAULT):ProtoChangeDetector{ | ||||
|   createProtoChangeDetector(name:string, bindingRecords:List, variableBindings:List, directiveRecords:List, | ||||
|                             changeControlStrategy:string=DEFAULT):ProtoChangeDetector{ | ||||
|     return null; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -28,7 +28,7 @@ import {DynamicChangeDetector} from './dynamic_change_detector'; | ||||
| import {ChangeDetectorJITGenerator} from './change_detection_jit_generator'; | ||||
| import {PipeRegistry} from './pipes/pipe_registry'; | ||||
| import {BindingRecord} from './binding_record'; | ||||
| import {DirectiveIndex} from './directive_record'; | ||||
| import {DirectiveRecord, DirectiveIndex} from './directive_record'; | ||||
| 
 | ||||
| import {coalesce} from './coalesce'; | ||||
| 
 | ||||
| @ -50,25 +50,31 @@ import { | ||||
| export class DynamicProtoChangeDetector extends ProtoChangeDetector { | ||||
|   _pipeRegistry:PipeRegistry; | ||||
|   _records:List<ProtoRecord>; | ||||
|   _bindingRecords:List<BindingRecord>; | ||||
|   _variableBindings:List<string>; | ||||
|   _directiveRecords:List<DirectiveRecord>; | ||||
|   _changeControlStrategy:string; | ||||
| 
 | ||||
|   constructor(pipeRegistry:PipeRegistry, changeControlStrategy:string) { | ||||
|   constructor(pipeRegistry:PipeRegistry, bindingRecords:List, variableBindings:List, directiveRecords:List, changeControlStrategy:string) { | ||||
|     super(); | ||||
|     this._pipeRegistry = pipeRegistry; | ||||
|     this._bindingRecords = bindingRecords; | ||||
|     this._variableBindings = variableBindings; | ||||
|     this._directiveRecords = directiveRecords; | ||||
|     this._changeControlStrategy = changeControlStrategy; | ||||
|   } | ||||
| 
 | ||||
|   instantiate(dispatcher:any, bindingRecords:List, variableBindings:List, directiveRecords:List) { | ||||
|     this._createRecordsIfNecessary(bindingRecords, variableBindings); | ||||
|   instantiate(dispatcher:any) { | ||||
|     this._createRecordsIfNecessary(); | ||||
|     return new DynamicChangeDetector(this._changeControlStrategy, dispatcher, | ||||
|       this._pipeRegistry, this._records, directiveRecords); | ||||
|       this._pipeRegistry, this._records, this._directiveRecords); | ||||
|   } | ||||
| 
 | ||||
|   _createRecordsIfNecessary(bindingRecords:List, variableBindings:List) { | ||||
|   _createRecordsIfNecessary() { | ||||
|     if (isBlank(this._records)) { | ||||
|       var recordBuilder = new ProtoRecordBuilder(); | ||||
|       ListWrapper.forEach(bindingRecords, (b) => { | ||||
|         recordBuilder.addAst(b, variableBindings); | ||||
|       ListWrapper.forEach(this._bindingRecords, (b) => { | ||||
|         recordBuilder.addAst(b, this._variableBindings); | ||||
|       }); | ||||
|       this._records = coalesce(recordBuilder.records); | ||||
|     } | ||||
| @ -79,31 +85,37 @@ var _jitProtoChangeDetectorClassCounter:number = 0; | ||||
| export class JitProtoChangeDetector extends ProtoChangeDetector { | ||||
|   _factory:Function; | ||||
|   _pipeRegistry; | ||||
|   _bindingRecords:List<BindingRecord>; | ||||
|   _variableBindings:List<string>; | ||||
|   _directiveRecords:List<DirectiveRecord>; | ||||
|   _changeControlStrategy:string; | ||||
| 
 | ||||
|   constructor(pipeRegistry, changeControlStrategy:string) { | ||||
|   constructor(pipeRegistry, bindingRecords:List, variableBindings:List, directiveRecords:List, changeControlStrategy:string) { | ||||
|     super(); | ||||
|     this._pipeRegistry = pipeRegistry; | ||||
|     this._factory = null; | ||||
|     this._bindingRecords = bindingRecords; | ||||
|     this._variableBindings = variableBindings; | ||||
|     this._directiveRecords = directiveRecords; | ||||
|     this._changeControlStrategy = changeControlStrategy; | ||||
|   } | ||||
| 
 | ||||
|   instantiate(dispatcher:any, bindingRecords:List, variableBindings:List, directiveRecords:List) { | ||||
|     this._createFactoryIfNecessary(bindingRecords, variableBindings, directiveRecords); | ||||
|   instantiate(dispatcher:any) { | ||||
|     this._createFactoryIfNecessary(); | ||||
|     return this._factory(dispatcher, this._pipeRegistry); | ||||
|   } | ||||
| 
 | ||||
|   _createFactoryIfNecessary(bindingRecords:List, variableBindings:List, directiveRecords:List) { | ||||
|   _createFactoryIfNecessary() { | ||||
|     if (isBlank(this._factory)) { | ||||
|       var recordBuilder = new ProtoRecordBuilder(); | ||||
|       ListWrapper.forEach(bindingRecords, (b) => { | ||||
|         recordBuilder.addAst(b, variableBindings); | ||||
|       ListWrapper.forEach(this._bindingRecords, (b) => { | ||||
|         recordBuilder.addAst(b, this._variableBindings); | ||||
|       }); | ||||
|       var c = _jitProtoChangeDetectorClassCounter++; | ||||
|       var records = coalesce(recordBuilder.records); | ||||
|       var typeName = `ChangeDetector${c}`; | ||||
|       this._factory = new ChangeDetectorJITGenerator(typeName, this._changeControlStrategy, records, | ||||
|         directiveRecords).generate(); | ||||
|         this._directiveRecords).generate(); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
							
								
								
									
										15
									
								
								modules/angular2/src/core/compiler/compiler.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								modules/angular2/src/core/compiler/compiler.js
									
									
									
									
										vendored
									
									
								
							| @ -94,7 +94,7 @@ export class Compiler { | ||||
| 
 | ||||
|     var directiveMetadata = Compiler.buildRenderDirective(componentBinding); | ||||
|     return this._renderer.createHostProtoView(directiveMetadata).then( (hostRenderPv) => { | ||||
|       return this._compileNestedProtoViews(null, hostRenderPv, [componentBinding], true); | ||||
|       return this._compileNestedProtoViews(null, null, hostRenderPv, [componentBinding], true); | ||||
|     }).then( (appProtoView) => { | ||||
|       return new ProtoViewRef(appProtoView); | ||||
|     }); | ||||
| @ -135,7 +135,7 @@ export class Compiler { | ||||
|     if (isPresent(template.renderer)) { | ||||
|       var directives = []; | ||||
|       pvPromise = this._renderer.createImperativeComponentProtoView(template.renderer).then( (renderPv) => { | ||||
|         return this._compileNestedProtoViews(componentBinding, renderPv, directives, true); | ||||
|         return this._compileNestedProtoViews(null, componentBinding, renderPv, directives, true); | ||||
|       }); | ||||
|     } else { | ||||
|       var directives = ListWrapper.map( | ||||
| @ -144,7 +144,7 @@ export class Compiler { | ||||
|       ); | ||||
|       var renderTemplate = this._buildRenderTemplate(component, template, directives); | ||||
|       pvPromise = this._renderer.compile(renderTemplate).then( (renderPv) => { | ||||
|         return this._compileNestedProtoViews(componentBinding, renderPv, directives, true); | ||||
|         return this._compileNestedProtoViews(null, componentBinding, renderPv, directives, true); | ||||
|       }); | ||||
|     } | ||||
| 
 | ||||
| @ -153,9 +153,9 @@ export class Compiler { | ||||
|   } | ||||
| 
 | ||||
|   // TODO(tbosch): union type return AppProtoView or Promise<AppProtoView>
 | ||||
|   _compileNestedProtoViews(componentBinding, renderPv, directives, isComponentRootView) { | ||||
|   _compileNestedProtoViews(parentProtoView, componentBinding, renderPv, directives, isComponentRootView) { | ||||
|     var nestedPVPromises = []; | ||||
|     var protoView = this._protoViewFactory.createProtoView(componentBinding, renderPv, directives); | ||||
|     var protoView = this._protoViewFactory.createProtoView(parentProtoView, componentBinding, renderPv, directives); | ||||
|     if (isComponentRootView && isPresent(componentBinding)) { | ||||
|       // Populate the cache before compiling the nested components,
 | ||||
|       // so that components can reference themselves in their template.
 | ||||
| @ -170,15 +170,12 @@ export class Compiler { | ||||
|       var nestedRenderProtoView = renderPv.elementBinders[binderIndex].nestedProtoView; | ||||
|       var elementBinderDone = (nestedPv) => { | ||||
|         elementBinder.nestedProtoView = nestedPv; | ||||
|         // Can't set the parentProtoView for components,
 | ||||
|         // as their AppProtoView might be used in multiple other components.
 | ||||
|         nestedPv.parentProtoView = isPresent(nestedComponent) ? null : protoView; | ||||
|       }; | ||||
|       var nestedCall = null; | ||||
|       if (isPresent(nestedComponent)) { | ||||
|         nestedCall = this._compile(nestedComponent); | ||||
|       } else if (isPresent(nestedRenderProtoView)) { | ||||
|         nestedCall = this._compileNestedProtoViews(componentBinding, nestedRenderProtoView, directives, false); | ||||
|         nestedCall = this._compileNestedProtoViews(protoView, componentBinding, nestedRenderProtoView, directives, false); | ||||
|       } | ||||
|       if (PromiseWrapper.isPromise(nestedCall)) { | ||||
|         ListWrapper.push(nestedPVPromises, nestedCall.then(elementBinderDone)); | ||||
|  | ||||
| @ -3,13 +3,103 @@ import {List, ListWrapper, MapWrapper} from 'angular2/src/facade/collection'; | ||||
| import {isPresent, isBlank} from 'angular2/src/facade/lang'; | ||||
| import {reflector} from 'angular2/src/reflection/reflection'; | ||||
| 
 | ||||
| import {ChangeDetection, DirectiveIndex} from 'angular2/change_detection'; | ||||
| import {ChangeDetection, DirectiveIndex, BindingRecord, DirectiveRecord, ProtoChangeDetector} from 'angular2/change_detection'; | ||||
| import {Component} from '../annotations_impl/annotations'; | ||||
| 
 | ||||
| import * as renderApi from 'angular2/src/render/api'; | ||||
| import {AppProtoView} from './view'; | ||||
| import {ProtoElementInjector, DirectiveBinding} from './element_injector'; | ||||
| 
 | ||||
| 
 | ||||
| class BindingRecordsCreator { | ||||
|   _directiveRecordsMap; | ||||
|   _textNodeIndex:number; | ||||
| 
 | ||||
|   constructor() { | ||||
|     this._directiveRecordsMap = MapWrapper.create(); | ||||
|     this._textNodeIndex = 0; | ||||
|   } | ||||
| 
 | ||||
|   getBindingRecords(elementBinders:List<renderApi.ElementBinder>, sortedDirectives:List<SortedDirectives>):List<BindingRecord> { | ||||
|     var bindings = []; | ||||
| 
 | ||||
|     for (var boundElementIndex = 0; boundElementIndex < elementBinders.length; boundElementIndex++) { | ||||
|       var renderElementBinder = elementBinders[boundElementIndex]; | ||||
|       bindings = ListWrapper.concat(bindings, this._createTextNodeRecords(renderElementBinder)); | ||||
|       bindings = ListWrapper.concat(bindings, this._createElementPropertyRecords(boundElementIndex, renderElementBinder)); | ||||
|       bindings = ListWrapper.concat(bindings, this._createDirectiveRecords(boundElementIndex, sortedDirectives[boundElementIndex])); | ||||
|     } | ||||
|      | ||||
|     return bindings; | ||||
|   } | ||||
| 
 | ||||
|   getDirectiveRecords(sortedDirectives:List<SortedDirectives>): List { | ||||
|     var directiveRecords = []; | ||||
| 
 | ||||
|     for (var elementIndex = 0; elementIndex < sortedDirectives.length; ++elementIndex) { | ||||
|       var dirs = sortedDirectives[elementIndex].directives; | ||||
|       for (var dirIndex = 0; dirIndex < dirs.length; ++dirIndex) { | ||||
|         ListWrapper.push(directiveRecords, this._getDirectiveRecord(elementIndex, dirIndex, dirs[dirIndex])); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     return directiveRecords; | ||||
|   } | ||||
| 
 | ||||
|   _createTextNodeRecords(renderElementBinder:renderApi.ElementBinder) { | ||||
|     if (isBlank(renderElementBinder.textBindings)) return []; | ||||
|     return ListWrapper.map(renderElementBinder.textBindings, b => BindingRecord.createForTextNode(b, this._textNodeIndex++)); | ||||
|   } | ||||
| 
 | ||||
|   _createElementPropertyRecords(boundElementIndex:number, renderElementBinder:renderApi.ElementBinder) { | ||||
|     var res = []; | ||||
|     MapWrapper.forEach(renderElementBinder.propertyBindings, (astWithSource, propertyName) => { | ||||
|       ListWrapper.push(res, BindingRecord.createForElement(astWithSource, boundElementIndex, propertyName)); | ||||
|     }); | ||||
|     return res; | ||||
|   } | ||||
| 
 | ||||
|   _createDirectiveRecords(boundElementIndex:number, sortedDirectives:SortedDirectives) { | ||||
|     var res = []; | ||||
|     for (var i = 0; i < sortedDirectives.renderDirectives.length; i++) { | ||||
|       var directiveBinder = sortedDirectives.renderDirectives[i]; | ||||
| 
 | ||||
|       // directive properties
 | ||||
|       MapWrapper.forEach(directiveBinder.propertyBindings, (astWithSource, propertyName) => { | ||||
|         // TODO: these setters should eventually be created by change detection, to make
 | ||||
|         // it monomorphic!
 | ||||
|         var setter = reflector.setter(propertyName); | ||||
|         var directiveRecord = this._getDirectiveRecord(boundElementIndex, i, sortedDirectives.directives[i]); | ||||
|         var b = BindingRecord.createForDirective(astWithSource, propertyName, setter, directiveRecord); | ||||
|         ListWrapper.push(res, b); | ||||
|       }); | ||||
| 
 | ||||
|       // host properties
 | ||||
|       MapWrapper.forEach(directiveBinder.hostPropertyBindings, (astWithSource, propertyName) => { | ||||
|         var dirIndex = new DirectiveIndex(boundElementIndex, i); | ||||
|         var b = BindingRecord.createForHostProperty(dirIndex, astWithSource, propertyName); | ||||
|         ListWrapper.push(res, b); | ||||
|       }); | ||||
|     } | ||||
|     return res; | ||||
|   } | ||||
| 
 | ||||
|   _getDirectiveRecord(boundElementIndex:number, directiveIndex:number, binding:DirectiveBinding): DirectiveRecord { | ||||
|     var id = boundElementIndex * 100 + directiveIndex; | ||||
| 
 | ||||
|     if (!MapWrapper.contains(this._directiveRecordsMap, id)) { | ||||
|       var changeDetection = binding.changeDetection; | ||||
| 
 | ||||
|       MapWrapper.set(this._directiveRecordsMap, id, | ||||
|         new DirectiveRecord(new DirectiveIndex(boundElementIndex, directiveIndex), | ||||
|           binding.callOnAllChangesDone, binding.callOnChange, changeDetection)); | ||||
|     } | ||||
| 
 | ||||
|     return MapWrapper.get(this._directiveRecordsMap, id); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| @Injectable() | ||||
| export class ProtoViewFactory { | ||||
|   _changeDetection:ChangeDetection; | ||||
| @ -18,40 +108,85 @@ export class ProtoViewFactory { | ||||
|     this._changeDetection = changeDetection; | ||||
|   } | ||||
| 
 | ||||
|   createProtoView(componentBinding:DirectiveBinding, renderProtoView: renderApi.ProtoViewDto, | ||||
|                   directives:List<DirectiveBinding>):AppProtoView { | ||||
|     var protoChangeDetector; | ||||
|     if (isBlank(componentBinding)) { | ||||
|       protoChangeDetector = this._changeDetection.createProtoChangeDetector('root', null); | ||||
|     } else { | ||||
|       var componentAnnotation:Component = componentBinding.annotation; | ||||
|       protoChangeDetector = this._changeDetection.createProtoChangeDetector( | ||||
|         'dummy', componentAnnotation.changeDetection | ||||
|       ); | ||||
|     } | ||||
|     var protoView = new AppProtoView(renderProtoView.render, protoChangeDetector); | ||||
|   createProtoView(parentProtoView:AppProtoView, componentBinding:DirectiveBinding, | ||||
|                   renderProtoView: renderApi.ProtoViewDto, directives:List<DirectiveBinding>):AppProtoView { | ||||
| 
 | ||||
|     var elementBinders = renderProtoView.elementBinders; | ||||
|     var sortedDirectives = ListWrapper.map(elementBinders, b => new SortedDirectives(b.directives, directives)); | ||||
| 
 | ||||
|     var variableBindings = this._createVariableBindings(renderProtoView); | ||||
|     var protoLocals = this._createProtoLocals(renderProtoView); | ||||
|     var variableNames = this._createVariableNames(parentProtoView, protoLocals); | ||||
|     var protoChangeDetector = this._createProtoChangeDetector(elementBinders, sortedDirectives, componentBinding, variableNames); | ||||
|     var protoView = new AppProtoView(renderProtoView.render, protoChangeDetector, variableBindings, protoLocals, variableNames); | ||||
| 
 | ||||
|     // TODO: vsavkin refactor to pass element binders into proto view
 | ||||
|     this._createElementBinders(protoView, elementBinders, sortedDirectives) | ||||
|     this._bindDirectiveEvents(protoView, sortedDirectives); | ||||
| 
 | ||||
|     for (var i=0; i<renderProtoView.elementBinders.length; i++) { | ||||
|       var renderElementBinder = renderProtoView.elementBinders[i]; | ||||
|       var sortedDirectives = new SortedDirectives(renderElementBinder.directives, directives); | ||||
|       var parentPeiWithDistance = this._findParentProtoElementInjectorWithDistance( | ||||
|         i, protoView.elementBinders, renderProtoView.elementBinders | ||||
|       ); | ||||
|       var protoElementInjector = this._createProtoElementInjector( | ||||
|         i, parentPeiWithDistance, | ||||
|         sortedDirectives, renderElementBinder | ||||
|       ); | ||||
|       this._createElementBinder( | ||||
|         protoView, renderElementBinder, protoElementInjector, sortedDirectives | ||||
|       ); | ||||
|       this._createDirectiveBinders(protoView, i, sortedDirectives); | ||||
|     } | ||||
|     MapWrapper.forEach(renderProtoView.variableBindings, (mappedName, varName) => { | ||||
|       protoView.bindVariable(varName, mappedName); | ||||
|     }); | ||||
|     return protoView; | ||||
|   } | ||||
| 
 | ||||
|   _createProtoLocals(renderProtoView):Map { | ||||
|     var protoLocals = MapWrapper.create(); | ||||
|     MapWrapper.forEach(renderProtoView.variableBindings, (mappedName, varName) => { | ||||
|       MapWrapper.set(protoLocals, mappedName, null); | ||||
|     }); | ||||
|     return protoLocals; | ||||
|   } | ||||
| 
 | ||||
|   _createVariableBindings(renderProtoView):Map { | ||||
|     var variableBindings = MapWrapper.create(); | ||||
|     MapWrapper.forEach(renderProtoView.variableBindings, (mappedName, varName) => { | ||||
|       MapWrapper.set(variableBindings, varName, mappedName); | ||||
|     }); | ||||
|     return variableBindings; | ||||
|   } | ||||
| 
 | ||||
|   _createVariableNames(parentProtoView, protoLocals):List { | ||||
|     var variableNames = isPresent(parentProtoView) ? ListWrapper.clone(parentProtoView.variableNames) : []; | ||||
|     MapWrapper.forEach(protoLocals, (v, local) => { | ||||
|       ListWrapper.push(variableNames, local); | ||||
|     }); | ||||
|     return variableNames; | ||||
|   } | ||||
| 
 | ||||
|   _createProtoChangeDetector(elementBinders, sortedDirectives, componentBinding, variableNames):ProtoChangeDetector { | ||||
|     var bindingRecordsCreator = new BindingRecordsCreator(); | ||||
|     var bindingRecords = bindingRecordsCreator.getBindingRecords(elementBinders, sortedDirectives); | ||||
|     var directiveRecords = bindingRecordsCreator.getDirectiveRecords(sortedDirectives); | ||||
| 
 | ||||
|     var changeDetection = null; | ||||
|     var name = 'root'; | ||||
|     if (isPresent(componentBinding)) { | ||||
|       var componentAnnotation:Component = componentBinding.annotation; | ||||
|       changeDetection = componentAnnotation.changeDetection; | ||||
|       name = 'dummy'; | ||||
|     } | ||||
| 
 | ||||
|     return this._changeDetection.createProtoChangeDetector( | ||||
|       name, | ||||
|       bindingRecords, | ||||
|       variableNames, | ||||
|       directiveRecords, | ||||
|       changeDetection | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   _createElementBinders(protoView, elementBinders, sortedDirectives) { | ||||
|     for (var i=0; i<elementBinders.length; i++) { | ||||
|       var renderElementBinder = elementBinders[i]; | ||||
|       var dirs = sortedDirectives[i]; | ||||
| 
 | ||||
|       var parentPeiWithDistance = this._findParentProtoElementInjectorWithDistance( | ||||
|           i, protoView.elementBinders, elementBinders); | ||||
|       var protoElementInjector = this._createProtoElementInjector( | ||||
|           i, parentPeiWithDistance, dirs, renderElementBinder); | ||||
| 
 | ||||
|       this._createElementBinder(protoView, i, renderElementBinder, protoElementInjector, dirs); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   _findParentProtoElementInjectorWithDistance(binderIndex, elementBinders, renderElementBinders) { | ||||
|     var distance = 0; | ||||
|     do { | ||||
| @ -95,7 +230,7 @@ export class ProtoViewFactory { | ||||
|     return protoElementInjector; | ||||
|   } | ||||
| 
 | ||||
|   _createElementBinder(protoView, renderElementBinder, protoElementInjector, sortedDirectives) { | ||||
|   _createElementBinder(protoView, boundElementIndex, renderElementBinder, protoElementInjector, sortedDirectives) { | ||||
|     var parent = null; | ||||
|     if (renderElementBinder.parentIndex !== -1) { | ||||
|       parent = protoView.elementBinders[renderElementBinder.parentIndex]; | ||||
| @ -106,16 +241,7 @@ export class ProtoViewFactory { | ||||
|       protoElementInjector, | ||||
|       sortedDirectives.componentDirective | ||||
|     ); | ||||
|     // text nodes
 | ||||
|     for (var i=0; i<renderElementBinder.textBindings.length; i++) { | ||||
|       protoView.bindTextNode(renderElementBinder.textBindings[i]); | ||||
|     } | ||||
|     // element properties
 | ||||
|     MapWrapper.forEach(renderElementBinder.propertyBindings, (astWithSource, propertyName) => { | ||||
|       protoView.bindElementProperty(astWithSource, propertyName); | ||||
|     }); | ||||
|     // events
 | ||||
|     protoView.bindEvent(renderElementBinder.eventBindings, -1); | ||||
|     protoView.bindEvent(renderElementBinder.eventBindings, boundElementIndex, -1); | ||||
|     // variables
 | ||||
|     // The view's locals needs to have a full set of variable names at construction time
 | ||||
|     // in order to prevent new variables from being set later in the lifecycle. Since we don't want
 | ||||
| @ -127,26 +253,15 @@ export class ProtoViewFactory { | ||||
|     return elBinder; | ||||
|   } | ||||
| 
 | ||||
|   _createDirectiveBinders(protoView, boundElementIndex, sortedDirectives) { | ||||
|     for (var i = 0; i < sortedDirectives.renderDirectives.length; i++) { | ||||
|       var directiveBinder = sortedDirectives.renderDirectives[i]; | ||||
|   _bindDirectiveEvents(protoView, sortedDirectives:List<SortedDirectives>) { | ||||
|     for (var boundElementIndex = 0; boundElementIndex < sortedDirectives.length; ++boundElementIndex) { | ||||
|       var dirs = sortedDirectives[boundElementIndex].renderDirectives; | ||||
|       for (var i = 0; i < dirs.length; i++) { | ||||
|         var directiveBinder = dirs[i]; | ||||
| 
 | ||||
|       // directive properties
 | ||||
|       MapWrapper.forEach(directiveBinder.propertyBindings, (astWithSource, propertyName) => { | ||||
|         // TODO: these setters should eventually be created by change detection, to make
 | ||||
|         // it monomorphic!
 | ||||
|         var setter = reflector.setter(propertyName); | ||||
|         protoView.bindDirectiveProperty(i, astWithSource, propertyName, setter); | ||||
|       }); | ||||
| 
 | ||||
|       // host properties
 | ||||
|       MapWrapper.forEach(directiveBinder.hostPropertyBindings, (astWithSource, propertyName) => { | ||||
|         var directiveIndex = new DirectiveIndex(boundElementIndex, i); | ||||
|         protoView.bindHostElementProperty(astWithSource, propertyName, directiveIndex); | ||||
|       }); | ||||
| 
 | ||||
|       // directive events
 | ||||
|       protoView.bindEvent(directiveBinder.eventBindings, i); | ||||
|         // directive events
 | ||||
|         protoView.bindEvent(directiveBinder.eventBindings, boundElementIndex, i); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
							
								
								
									
										130
									
								
								modules/angular2/src/core/compiler/view.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										130
									
								
								modules/angular2/src/core/compiler/view.js
									
									
									
									
										vendored
									
									
								
							| @ -4,7 +4,6 @@ import {AST, Locals, ChangeDispatcher, ProtoChangeDetector, ChangeDetector, | ||||
| 
 | ||||
| import {ProtoElementInjector, ElementInjector, PreBuiltObjects, DirectiveBinding} from './element_injector'; | ||||
| import {ElementBinder} from './element_binder'; | ||||
| import {SetterFn} from 'angular2/src/reflection/types'; | ||||
| import {IMPLEMENTS, int, isPresent, isBlank, BaseException} from 'angular2/src/facade/lang'; | ||||
| import * as renderApi from 'angular2/src/render/api'; | ||||
| 
 | ||||
| @ -164,74 +163,22 @@ export class AppProtoView { | ||||
|   protoChangeDetector:ProtoChangeDetector; | ||||
|   variableBindings: Map; | ||||
|   protoLocals:Map; | ||||
|   textNodesWithBindingCount:int; | ||||
|   bindings:List; | ||||
|   parentProtoView:AppProtoView; | ||||
|   _variableBindings:List; | ||||
| 
 | ||||
|   _directiveRecordsMap:Map; | ||||
|   _directiveRecords:List; | ||||
|   variableNames:List; | ||||
|   render:renderApi.RenderProtoViewRef; | ||||
| 
 | ||||
|   constructor( | ||||
|       render:renderApi.RenderProtoViewRef, | ||||
|       protoChangeDetector:ProtoChangeDetector) { | ||||
|       protoChangeDetector:ProtoChangeDetector, | ||||
|       variableBindings:Map, | ||||
|       protoLocals:Map, | ||||
|       variableNames:List) { | ||||
|     this.render = render; | ||||
|     this.elementBinders = []; | ||||
|     this.variableBindings = MapWrapper.create(); | ||||
|     this.protoLocals = MapWrapper.create(); | ||||
|     this.variableBindings = variableBindings; | ||||
|     this.protoLocals = protoLocals; | ||||
|     this.variableNames = variableNames; | ||||
|     this.protoChangeDetector = protoChangeDetector; | ||||
|     this.parentProtoView = null; | ||||
|     this.textNodesWithBindingCount = 0; | ||||
|     this.bindings = []; | ||||
|     this._directiveRecordsMap = MapWrapper.create(); | ||||
|     this._variableBindings = null; | ||||
|     this._directiveRecords = null; | ||||
|   } | ||||
| 
 | ||||
|   //TODO: Tobias or Victor. Moving it into the constructor.
 | ||||
|   // this work should be done the constructor of AppProtoView once we separate
 | ||||
|   // AppProtoView and ProtoViewBuilder
 | ||||
|   getVariableBindings(): List { | ||||
|     if (isPresent(this._variableBindings)) { | ||||
|       return this._variableBindings; | ||||
|     } | ||||
| 
 | ||||
|     this._variableBindings = isPresent(this.parentProtoView) ? | ||||
|       ListWrapper.clone(this.parentProtoView.getVariableBindings()) : []; | ||||
| 
 | ||||
|     MapWrapper.forEach(this.protoLocals, (v, local) => { | ||||
|       ListWrapper.push(this._variableBindings, local); | ||||
|     }); | ||||
| 
 | ||||
|     return this._variableBindings; | ||||
|   } | ||||
| 
 | ||||
|   //TODO: Tobias or Victor. Moving it into the constructor.
 | ||||
|   // this work should be done the constructor of ProtoView once we separate
 | ||||
|   // AppProtoView and ProtoViewBuilder
 | ||||
|   getdirectiveRecords(): List { | ||||
|     if (isPresent(this._directiveRecords)) { | ||||
|       return this._directiveRecords; | ||||
|     } | ||||
| 
 | ||||
|     this._directiveRecords = []; | ||||
| 
 | ||||
|     for (var injectorIndex = 0; injectorIndex < this.elementBinders.length; ++injectorIndex) { | ||||
|       var pei = this.elementBinders[injectorIndex].protoElementInjector; | ||||
|       if (isPresent(pei)) { | ||||
|         for (var directiveIndex = 0; directiveIndex < pei.numberOfDirectives; ++directiveIndex) { | ||||
|           ListWrapper.push(this._directiveRecords, this._getDirectiveRecord(injectorIndex, directiveIndex)); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     return this._directiveRecords; | ||||
|   } | ||||
| 
 | ||||
|   bindVariable(contextName:string, templateName:string): void { | ||||
|     MapWrapper.set(this.variableBindings, contextName, templateName); | ||||
|     MapWrapper.set(this.protoLocals, templateName, null); | ||||
|   } | ||||
| 
 | ||||
|   bindElement(parent:ElementBinder, distanceToParent:int, protoElementInjector:ProtoElementInjector, | ||||
| @ -242,32 +189,6 @@ export class AppProtoView { | ||||
|     return elBinder; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Adds a text node binding for the last created ElementBinder via bindElement | ||||
|    */ | ||||
|   bindTextNode(expression:AST):void { | ||||
|     var textNodeIndex = this.textNodesWithBindingCount++; | ||||
|     var b = BindingRecord.createForTextNode(expression, textNodeIndex); | ||||
|     ListWrapper.push(this.bindings, b); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Adds an element property binding for the last created ElementBinder via bindElement | ||||
|    */ | ||||
|   bindElementProperty(expression:AST, setterName:string):void { | ||||
|     var elementIndex = this.elementBinders.length-1; | ||||
|     var b = BindingRecord.createForElement(expression, elementIndex, setterName); | ||||
|     ListWrapper.push(this.bindings, b); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Adds an host property binding for the last created ElementBinder via bindElement | ||||
|    */ | ||||
|   bindHostElementProperty(expression:AST, setterName:string, directiveIndex:DirectiveIndex):void { | ||||
|     var b = BindingRecord.createForHostProperty(directiveIndex, expression, setterName); | ||||
|     ListWrapper.push(this.bindings, b); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Adds an event binding for the last created ElementBinder via bindElement. | ||||
|    * | ||||
| @ -281,8 +202,8 @@ export class AppProtoView { | ||||
|    * @param {int} directiveIndex The directive index in the binder or -1 when the event is not bound | ||||
|    *                             to a directive | ||||
|    */ | ||||
|   bindEvent(eventBindings: List<renderApi.EventBinding>, directiveIndex: int = -1): void { | ||||
|     var elBinder = this.elementBinders[this.elementBinders.length - 1]; | ||||
|   bindEvent(eventBindings: List<renderApi.EventBinding>, boundElementIndex:number, directiveIndex: int = -1): void { | ||||
|     var elBinder = this.elementBinders[boundElementIndex]; | ||||
|     var events = elBinder.hostListeners; | ||||
|     if (isBlank(events)) { | ||||
|       events = StringMapWrapper.create(); | ||||
| @ -299,35 +220,4 @@ export class AppProtoView { | ||||
|       MapWrapper.set(event, directiveIndex, eventBinding.source); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Adds a directive property binding for the last created ElementBinder via bindElement | ||||
|    */ | ||||
|   bindDirectiveProperty( | ||||
|     directiveIndex:number, | ||||
|     expression:AST, | ||||
|     setterName:string, | ||||
|     setter:SetterFn): void { | ||||
| 
 | ||||
|     var elementIndex = this.elementBinders.length-1; | ||||
|     var directiveRecord = this._getDirectiveRecord(elementIndex, directiveIndex); | ||||
|     var b = BindingRecord.createForDirective(expression, setterName, setter, directiveRecord); | ||||
|     ListWrapper.push(this.bindings, b); | ||||
|   } | ||||
| 
 | ||||
|   _getDirectiveRecord(elementInjectorIndex:number, directiveIndex:number): DirectiveRecord { | ||||
|     var id = elementInjectorIndex * 100 + directiveIndex; | ||||
|     var protoElementInjector = this.elementBinders[elementInjectorIndex].protoElementInjector; | ||||
| 
 | ||||
|     if (!MapWrapper.contains(this._directiveRecordsMap, id)) { | ||||
|       var binding = protoElementInjector.getDirectiveBindingAtIndex(directiveIndex); | ||||
|       var changeDetection = binding.changeDetection; | ||||
| 
 | ||||
|       MapWrapper.set(this._directiveRecordsMap, id, | ||||
|         new DirectiveRecord(new DirectiveIndex(elementInjectorIndex, directiveIndex), | ||||
|           binding.callOnAllChangesDone, binding.callOnChange, changeDetection)); | ||||
|     } | ||||
| 
 | ||||
|     return MapWrapper.get(this._directiveRecordsMap, id); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -28,8 +28,7 @@ export class AppViewManagerUtils { | ||||
| 
 | ||||
|   createView(protoView:viewModule.AppProtoView, viewManager:avmModule.AppViewManager, renderer:Renderer): viewModule.AppView { | ||||
|     var view = new viewModule.AppView(renderer, protoView, protoView.protoLocals); | ||||
|     var changeDetector = protoView.protoChangeDetector.instantiate(view, protoView.bindings, | ||||
|       protoView.getVariableBindings(), protoView.getdirectiveRecords()); | ||||
|     var changeDetector = protoView.protoChangeDetector.instantiate(view); | ||||
| 
 | ||||
|     var binders = protoView.elementBinders; | ||||
|     var elementInjectors = ListWrapper.createFixedSize(binders.length); | ||||
|  | ||||
| @ -16,8 +16,22 @@ import {JitProtoChangeDetector, DynamicProtoChangeDetector} from 'angular2/src/c | ||||
| export function main() { | ||||
|   describe("change detection", () => { | ||||
|     StringMapWrapper.forEach( | ||||
|       { "dynamic": (registry = null, strategy = null) => new DynamicProtoChangeDetector(registry, strategy), | ||||
|         "JIT": (registry = null, strategy = null) => new JitProtoChangeDetector(registry, strategy) | ||||
|       { "dynamic": (bindingRecords, variableBindings = null, directiveRecords = null, registry = null, strategy = null) => | ||||
|                       new DynamicProtoChangeDetector( | ||||
|                         registry, | ||||
|                         isBlank(bindingRecords) ? [] : bindingRecords, | ||||
|                         isBlank(variableBindings) ? [] : variableBindings, | ||||
|                         isBlank(directiveRecords) ? [] : directiveRecords, | ||||
|                         strategy), | ||||
| 
 | ||||
|         "JIT": (bindingRecords, variableBindings = null, directiveRecords = null, registry = null, strategy = null) => | ||||
|                       new JitProtoChangeDetector( | ||||
|                         registry, | ||||
|                         isBlank(bindingRecords) ? [] : bindingRecords, | ||||
|                         isBlank(variableBindings) ? [] : variableBindings, | ||||
|                         isBlank(directiveRecords) ? [] : directiveRecords, | ||||
|                         strategy) | ||||
| 
 | ||||
|       }, (createProtoChangeDetector, name) => { | ||||
| 
 | ||||
|         if (name == "JIT" && IS_DARTIUM) return; | ||||
| @ -43,13 +57,13 @@ export function main() { | ||||
|         } | ||||
| 
 | ||||
|         function createChangeDetector(propName:string, exp:string, context = null, locals = null, registry = null) { | ||||
|           var pcd = createProtoChangeDetector(registry); | ||||
|           var dispatcher = new TestDispatcher(); | ||||
| 
 | ||||
|           var variableBindings = convertLocalsToVariableBindings(locals); | ||||
| 
 | ||||
|           var records = [BindingRecord.createForElement(ast(exp), 0, propName)]; | ||||
|           var cd = pcd.instantiate(dispatcher, records, variableBindings, []); | ||||
|           var pcd = createProtoChangeDetector(records, variableBindings, [], registry); | ||||
|           var cd = pcd.instantiate(dispatcher); | ||||
|           cd.hydrate(context, locals, null); | ||||
| 
 | ||||
|           return {"changeDetector" : cd, "dispatcher" : dispatcher}; | ||||
| @ -61,11 +75,6 @@ export function main() { | ||||
|           return res["dispatcher"].log; | ||||
|         } | ||||
| 
 | ||||
|         function instantiate(protoChangeDetector, dispatcher, bindings, directiveRecords = null) { | ||||
|           if (isBlank(directiveRecords)) directiveRecords = []; | ||||
|           return protoChangeDetector.instantiate(dispatcher, bindings, null, directiveRecords); | ||||
|         } | ||||
| 
 | ||||
|         describe(`${name} change detection`, () => { | ||||
|           var dispatcher; | ||||
| 
 | ||||
| @ -205,10 +214,10 @@ export function main() { | ||||
|           }); | ||||
| 
 | ||||
|           it("should support interpolation", () => { | ||||
|             var pcd = createProtoChangeDetector(); | ||||
|             var ast = parser.parseInterpolation("B{{a}}A", "location"); | ||||
|             var pcd = createProtoChangeDetector([BindingRecord.createForElement(ast, 0, "memo")]); | ||||
| 
 | ||||
|             var cd = instantiate(pcd, dispatcher, [BindingRecord.createForElement(ast, 0, "memo")]); | ||||
|             var cd = pcd.instantiate(dispatcher); | ||||
|             cd.hydrate(new TestData("value"), null, null); | ||||
| 
 | ||||
|             cd.detectChanges(); | ||||
| @ -267,10 +276,9 @@ export function main() { | ||||
|               }); | ||||
| 
 | ||||
|               it("should happen directly, without invoking the dispatcher", () => { | ||||
|                 var pcd = createProtoChangeDetector(); | ||||
|                 var pcd = createProtoChangeDetector([updateA("42", dirRecord1)], [], [dirRecord1]); | ||||
| 
 | ||||
|                 var cd = instantiate(pcd, dispatcher, [updateA("42", dirRecord1)], | ||||
|                   [dirRecord1]); | ||||
|                 var cd = pcd.instantiate(dispatcher); | ||||
| 
 | ||||
|                 cd.hydrate(null, null, dirs([directive1])); | ||||
| 
 | ||||
| @ -282,13 +290,13 @@ export function main() { | ||||
| 
 | ||||
|               describe("onChange", () => { | ||||
|                 it("should notify the directive when a group of records changes", () => { | ||||
|                   var pcd = createProtoChangeDetector(); | ||||
| 
 | ||||
|                   var cd = instantiate(pcd, dispatcher, [ | ||||
|                   var pcd = createProtoChangeDetector([ | ||||
|                     updateA("1", dirRecord1), | ||||
|                     updateB("2", dirRecord1), | ||||
|                     updateA("3", dirRecord2) | ||||
|                   ], [dirRecord1, dirRecord2]); | ||||
|                   ], [], [dirRecord1, dirRecord2]); | ||||
| 
 | ||||
|                   var cd = pcd.instantiate(dispatcher); | ||||
| 
 | ||||
|                   cd.hydrate(null, null, dirs([directive1, directive2])); | ||||
| 
 | ||||
| @ -299,11 +307,11 @@ export function main() { | ||||
|                 }); | ||||
| 
 | ||||
|                 it("should not call onChange when callOnChange is false", () => { | ||||
|                   var pcd = createProtoChangeDetector(); | ||||
| 
 | ||||
|                   var cd = instantiate(pcd, dispatcher, [ | ||||
|                   var pcd = createProtoChangeDetector([ | ||||
|                     updateA("1", dirRecordNoCallbacks) | ||||
|                   ], [dirRecordNoCallbacks]); | ||||
|                   ], [], [dirRecordNoCallbacks]); | ||||
| 
 | ||||
|                   var cd = pcd.instantiate(dispatcher); | ||||
| 
 | ||||
|                   cd.hydrate(null, null, dirs([directive1])); | ||||
| 
 | ||||
| @ -315,9 +323,9 @@ export function main() { | ||||
| 
 | ||||
|               describe("onAllChangesDone", () => { | ||||
|                 it("should be called after processing all the children", () => { | ||||
|                   var pcd = createProtoChangeDetector(); | ||||
|                   var pcd = createProtoChangeDetector([], [], [dirRecord1, dirRecord2]); | ||||
| 
 | ||||
|                   var cd = instantiate(pcd, dispatcher, [], [dirRecord1, dirRecord2]); | ||||
|                   var cd = pcd.instantiate(dispatcher); | ||||
|                   cd.hydrate(null, null, dirs([directive1, directive2])); | ||||
| 
 | ||||
|                   cd.detectChanges(); | ||||
| @ -328,11 +336,11 @@ export function main() { | ||||
| 
 | ||||
| 
 | ||||
|                 it("should not be called when onAllChangesDone is false", () => { | ||||
|                   var pcd = createProtoChangeDetector(); | ||||
| 
 | ||||
|                   var cd = instantiate(pcd, dispatcher, [ | ||||
|                   var pcd = createProtoChangeDetector([ | ||||
|                     updateA("1", dirRecordNoCallbacks) | ||||
|                   ], [dirRecordNoCallbacks]); | ||||
|                   ], [], [dirRecordNoCallbacks]); | ||||
| 
 | ||||
|                   var cd = pcd.instantiate(dispatcher); | ||||
| 
 | ||||
|                   cd.hydrate(null, null, dirs([directive1])); | ||||
| 
 | ||||
| @ -342,8 +350,8 @@ export function main() { | ||||
|                 }); | ||||
| 
 | ||||
|                 it("should be called in reverse order so the child is always notified before the parent", () => { | ||||
|                   var pcd = createProtoChangeDetector(); | ||||
|                   var cd = instantiate(pcd, dispatcher, [], [dirRecord1, dirRecord2]); | ||||
|                   var pcd = createProtoChangeDetector([], [], [dirRecord1, dirRecord2]); | ||||
|                   var cd = pcd.instantiate(dispatcher); | ||||
| 
 | ||||
|                   var onChangesDoneCalls = []; | ||||
|                   var td1; | ||||
| @ -358,13 +366,12 @@ export function main() { | ||||
|                 }); | ||||
| 
 | ||||
|                 it("should be called before processing shadow dom children", () => { | ||||
|                   var pcd = createProtoChangeDetector(); | ||||
|                   var shadowDomChildPCD = createProtoChangeDetector(); | ||||
|                   var pcd = createProtoChangeDetector([], null, [dirRecord1]); | ||||
|                   var shadowDomChildPCD = createProtoChangeDetector([updateA("1", dirRecord1)], null, [dirRecord1]); | ||||
| 
 | ||||
|                   var parent = pcd.instantiate(dispatcher, [], null, [dirRecord1]); | ||||
|                   var parent = pcd.instantiate(dispatcher); | ||||
| 
 | ||||
|                   var child = shadowDomChildPCD.instantiate(dispatcher, | ||||
|                     [updateA("1", dirRecord1)], null, [dirRecord1]); | ||||
|                   var child = shadowDomChildPCD.instantiate(dispatcher); | ||||
|                   parent.addShadowDomChild(child); | ||||
| 
 | ||||
|                   var directiveInShadowDom = new TestDirective(); | ||||
| @ -389,8 +396,8 @@ export function main() { | ||||
|               var directive = new TestDirective(); | ||||
|               directive.a = "aaa"; | ||||
| 
 | ||||
|               var pcd = createProtoChangeDetector(); | ||||
|               var cd = instantiate(pcd, dispatcher, [BindingRecord.createForHostProperty(index, ast("a"), "prop")], [dirRecord]); | ||||
|               var pcd = createProtoChangeDetector([BindingRecord.createForHostProperty(index, ast("a"), "prop")], null, [dirRecord]); | ||||
|               var cd = pcd.instantiate(dispatcher); | ||||
|               cd.hydrate(null, null, dirs([directive])); | ||||
| 
 | ||||
|               cd.detectChanges(); | ||||
| @ -401,12 +408,12 @@ export function main() { | ||||
| 
 | ||||
|           describe("enforce no new changes", () => { | ||||
|             it("should throw when a record gets changed after it has been checked", () => { | ||||
|               var pcd = createProtoChangeDetector(); | ||||
| 
 | ||||
|               var dispatcher = new TestDispatcher(); | ||||
|               var cd = instantiate(pcd, dispatcher, [ | ||||
|               var pcd = createProtoChangeDetector([ | ||||
|                 BindingRecord.createForElement(ast("a"), 0, "a") | ||||
|               ]); | ||||
| 
 | ||||
|               var dispatcher = new TestDispatcher(); | ||||
|               var cd = pcd.instantiate(dispatcher); | ||||
|               cd.hydrate(new TestData('value'), null, null); | ||||
| 
 | ||||
|               expect(() => { | ||||
| @ -487,11 +494,8 @@ export function main() { | ||||
|             var parent, child; | ||||
| 
 | ||||
|             beforeEach(() => { | ||||
|               var protoParent = createProtoChangeDetector(); | ||||
|               parent = instantiate(protoParent, null, []); | ||||
| 
 | ||||
|               var protoChild = createProtoChangeDetector(); | ||||
|               child = instantiate(protoChild, null, []); | ||||
|               parent = createProtoChangeDetector([]).instantiate(null); | ||||
|               child = createProtoChangeDetector([]).instantiate(null); | ||||
|             }); | ||||
| 
 | ||||
|             it("should add light dom children", () => { | ||||
| @ -526,8 +530,8 @@ export function main() { | ||||
| 
 | ||||
|         describe("mode", () => { | ||||
|           it("should set the mode to CHECK_ALWAYS when the default change detection is used", () => { | ||||
|             var proto = createProtoChangeDetector(null, DEFAULT); | ||||
|             var cd = proto.instantiate(null, [], [], []); | ||||
|             var proto = createProtoChangeDetector([], [], [], null, DEFAULT); | ||||
|             var cd = proto.instantiate(null); | ||||
| 
 | ||||
|             expect(cd.mode).toEqual(null); | ||||
| 
 | ||||
| @ -537,8 +541,8 @@ export function main() { | ||||
|           }); | ||||
| 
 | ||||
|           it("should set the mode to CHECK_ONCE when the push change detection is used", () => { | ||||
|             var proto = createProtoChangeDetector(null, ON_PUSH); | ||||
|             var cd = proto.instantiate(null, [], [], []); | ||||
|             var proto = createProtoChangeDetector([], [], [], null, ON_PUSH); | ||||
|             var cd = proto.instantiate(null); | ||||
|             cd.hydrate(null, null, null); | ||||
| 
 | ||||
|             expect(cd.mode).toEqual(CHECK_ONCE); | ||||
| @ -567,7 +571,7 @@ export function main() { | ||||
|           }); | ||||
| 
 | ||||
|           it("should change CHECK_ONCE to CHECKED", () => { | ||||
|             var cd = instantiate(createProtoChangeDetector(), null, []); | ||||
|             var cd = createProtoChangeDetector([]).instantiate(null); | ||||
|             cd.mode = CHECK_ONCE; | ||||
| 
 | ||||
|             cd.detectChanges(); | ||||
| @ -576,7 +580,7 @@ export function main() { | ||||
|           }); | ||||
| 
 | ||||
|           it("should not change the CHECK_ALWAYS", () => { | ||||
|             var cd = instantiate(createProtoChangeDetector(), null, []); | ||||
|             var cd = createProtoChangeDetector([]).instantiate(null); | ||||
|             cd.mode = CHECK_ALWAYS; | ||||
| 
 | ||||
|             cd.detectChanges(); | ||||
| @ -591,8 +595,8 @@ export function main() { | ||||
|             var directives; | ||||
| 
 | ||||
|             beforeEach(() => { | ||||
|               var proto = createProtoChangeDetector(null, ON_PUSH); | ||||
|               checkedDetector = instantiate(proto, null, [], []); | ||||
|               var proto = createProtoChangeDetector([], [], [], null, ON_PUSH); | ||||
|               checkedDetector = proto.instantiate(null); | ||||
|               checkedDetector.hydrate(null, null, null); | ||||
|               checkedDetector.mode = CHECKED; | ||||
| 
 | ||||
| @ -608,9 +612,9 @@ export function main() { | ||||
|             }); | ||||
| 
 | ||||
|             it("should set the mode to CHECK_ONCE when a binding is updated", () => { | ||||
|               var proto = createProtoChangeDetector(null); | ||||
|               var proto = createProtoChangeDetector([updateDirWithOnPushRecord], [], [dirRecordWithOnPush]); | ||||
| 
 | ||||
|               var cd = instantiate(proto, null, [updateDirWithOnPushRecord], [dirRecordWithOnPush]); | ||||
|               var cd = proto.instantiate(null); | ||||
|               cd.hydrate(null, null, directives); | ||||
| 
 | ||||
|               expect(checkedDetector.mode).toEqual(CHECKED); | ||||
| @ -625,7 +629,7 @@ export function main() { | ||||
| 
 | ||||
|         describe("markPathToRootAsCheckOnce", () => { | ||||
|           function changeDetector(mode, parent) { | ||||
|             var cd = instantiate(createProtoChangeDetector(), null, []); | ||||
|             var cd = createProtoChangeDetector([]).instantiate(null); | ||||
|             cd.mode = mode; | ||||
|             if (isPresent(parent)) parent.addChild(cd); | ||||
|             return cd; | ||||
|  | ||||
| @ -283,9 +283,6 @@ export function main() { | ||||
|       compiler.compile(MainComponent).then( (protoViewRef) => { | ||||
|         expect(internalProtoView(protoViewRef)).toBe(mainProtoView); | ||||
|         expect(mainProtoView.elementBinders[0].nestedProtoView).toBe(nestedProtoView); | ||||
|         // parentProtoView of nested components has to be null as components can
 | ||||
|         // be used by multiple other components.
 | ||||
|         expect(nestedProtoView.parentProtoView).toBe(null); | ||||
|         async.done(); | ||||
|       }); | ||||
|     })); | ||||
| @ -316,11 +313,7 @@ export function main() { | ||||
|       compiler.compile(MainComponent).then( (protoViewRef) => { | ||||
|         expect(internalProtoView(protoViewRef)).toBe(mainProtoView); | ||||
|         expect(mainProtoView.elementBinders[0].nestedProtoView).toBe(viewportProtoView); | ||||
|         expect(viewportProtoView.parentProtoView).toBe(mainProtoView); | ||||
|         expect(viewportProtoView.elementBinders[0].nestedProtoView).toBe(nestedProtoView); | ||||
|         // parentProtoView of nested components has to be null as components can
 | ||||
|         // be used by multiple other components.
 | ||||
|         expect(nestedProtoView.parentProtoView).toBe(null); | ||||
| 
 | ||||
|         async.done(); | ||||
|       }); | ||||
| @ -432,7 +425,7 @@ function createDirectiveBinding(reader, type) { | ||||
| } | ||||
| 
 | ||||
| function createProtoView(elementBinders = null) { | ||||
|   var pv = new AppProtoView(null, null); | ||||
|   var pv = new AppProtoView(null, null, null, null, null); | ||||
|   if (isBlank(elementBinders)) { | ||||
|     elementBinders = []; | ||||
|   } | ||||
| @ -575,7 +568,7 @@ class FakeProtoViewFactory extends ProtoViewFactory { | ||||
|     this._results = results; | ||||
|   } | ||||
| 
 | ||||
|   createProtoView(componentBinding:DirectiveBinding, renderProtoView: renderApi.ProtoViewDto, | ||||
|   createProtoView(parentProtoView, componentBinding:DirectiveBinding, renderProtoView: renderApi.ProtoViewDto, | ||||
|                   directives:List<DirectiveBinding>):AppProtoView { | ||||
|     ListWrapper.push(this.requests, [componentBinding, renderProtoView, directives]); | ||||
|     return ListWrapper.removeAt(this._results, 0); | ||||
|  | ||||
| @ -453,7 +453,7 @@ export function main() { | ||||
|       }); | ||||
| 
 | ||||
|       it("should instantiate directives that depend on pre built objects", function () { | ||||
|         var protoView = new AppProtoView(null, null); | ||||
|         var protoView = new AppProtoView(null, null, null, null, null); | ||||
|         var inj = injector([NeedsProtoViewRef], null, null, new PreBuiltObjects(null, null, protoView)); | ||||
| 
 | ||||
|         expect(inj.get(NeedsProtoViewRef).protoViewRef).toEqual(new ProtoViewRef(protoView)); | ||||
| @ -700,7 +700,7 @@ export function main() { | ||||
|       }); | ||||
| 
 | ||||
|       it("should inject ProtoViewRef", function () { | ||||
|         var protoView = new AppProtoView(null, null); | ||||
|         var protoView = new AppProtoView(null, null, null, null, null); | ||||
|         var inj = injector([NeedsProtoViewRef], null, null, new PreBuiltObjects(null, null, protoView)); | ||||
| 
 | ||||
|         expect(inj.get(NeedsProtoViewRef).protoViewRef).toEqual(new ProtoViewRef(protoView)); | ||||
|  | ||||
| @ -14,6 +14,7 @@ import { | ||||
|   xit | ||||
| } from 'angular2/test_lib'; | ||||
| 
 | ||||
| 
 | ||||
| import {TestBed} from 'angular2/src/test_lib/test_bed'; | ||||
| 
 | ||||
| import {DOM} from 'angular2/src/dom/dom_adapter'; | ||||
| @ -46,6 +47,7 @@ export function main() { | ||||
|       ctx = new MyComp(); | ||||
|     }); | ||||
| 
 | ||||
| 
 | ||||
|     describe('react to record changes', function() { | ||||
|       it('should consume text node changes', inject([TestBed, AsyncTestCompleter], (tb, async) => { | ||||
|         tb.overrideView(MyComp, new View({template: '<div>{{ctxProp}}</div>'})); | ||||
|  | ||||
| @ -37,7 +37,7 @@ export function main() { | ||||
|     } | ||||
| 
 | ||||
|     function createProtoView() { | ||||
|       return new AppProtoView(null, null); | ||||
|       return new AppProtoView(null, null, null, null, null); | ||||
|     } | ||||
| 
 | ||||
|     function createView() { | ||||
|  | ||||
| @ -80,7 +80,7 @@ export function main() { | ||||
|           staticChildComponentCount++; | ||||
|         } | ||||
|       } | ||||
|       var res = new AppProtoView(new MockProtoViewRef(staticChildComponentCount), null); | ||||
|       var res = new AppProtoView(new MockProtoViewRef(staticChildComponentCount), null, null, null, null); | ||||
|       res.elementBinders = binders; | ||||
|       return res; | ||||
|     } | ||||
|  | ||||
| @ -60,7 +60,7 @@ export function main() { | ||||
|       if (isBlank(binders)) { | ||||
|         binders = []; | ||||
|       } | ||||
|       var res = new AppProtoView(null, null); | ||||
|       var res = new AppProtoView(null, null, null, null, null); | ||||
|       res.elementBinders = binders; | ||||
|       return res; | ||||
|     } | ||||
|  | ||||
| @ -26,7 +26,7 @@ export function main() { | ||||
|     } | ||||
| 
 | ||||
|     function createProtoView() { | ||||
|       return new AppProtoView(null, null); | ||||
|       return new AppProtoView(null, null, null, null, null); | ||||
|     } | ||||
| 
 | ||||
|     function createView(pv) { | ||||
|  | ||||
| @ -187,10 +187,8 @@ function setUpChangeDetection(changeDetection:ChangeDetection, iterations, objec | ||||
|   var dispatcher = new DummyDispatcher(); | ||||
|   var parser = new Parser(new Lexer()); | ||||
| 
 | ||||
|   var parentProto = changeDetection.createProtoChangeDetector('parent'); | ||||
|   var parentCd = parentProto.instantiate(dispatcher, [], [], []); | ||||
| 
 | ||||
|   var proto = changeDetection.createProtoChangeDetector("proto"); | ||||
|   var parentProto = changeDetection.createProtoChangeDetector('parent', [], [], []); | ||||
|   var parentCd = parentProto.instantiate(dispatcher); | ||||
| 
 | ||||
|   var directiveRecord = new DirectiveRecord(new DirectiveIndex(0, 0), false, false, DEFAULT); | ||||
|   var bindings = [ | ||||
| @ -206,9 +204,11 @@ function setUpChangeDetection(changeDetection:ChangeDetection, iterations, objec | ||||
|     BindingRecord.createForDirective(parser.parseBinding('field9', null), "field9", reflector.setter("field9"), directiveRecord) | ||||
|   ]; | ||||
| 
 | ||||
|   var proto = changeDetection.createProtoChangeDetector("proto", bindings, [], [directiveRecord]); | ||||
| 
 | ||||
|   var targetObj = new Obj(); | ||||
|   for (var i = 0; i < iterations; ++i) { | ||||
|     var cd = proto.instantiate(dispatcher, bindings, [], [directiveRecord]); | ||||
|     var cd = proto.instantiate(dispatcher); | ||||
|     cd.hydrate(object, null, new FakeDirectives(targetObj)); | ||||
|     parentCd.addChild(cd); | ||||
|   } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user