diff --git a/modules/angular2/change_detection.js b/modules/angular2/change_detection.js index 064ca33a77..a6ff92d713 100644 --- a/modules/angular2/change_detection.js +++ b/modules/angular2/change_detection.js @@ -9,8 +9,12 @@ export {ExpressionChangedAfterItHasBeenChecked, ChangeDetectionError} from './src/change_detection/exceptions'; export {ProtoChangeDetector, ChangeDispatcher, ChangeDetector, ChangeDetection} from './src/change_detection/interfaces'; export {CHECK_ONCE, CHECK_ALWAYS, DETACHED, CHECKED, ON_PUSH, DEFAULT} from './src/change_detection/constants'; -export {DynamicProtoChangeDetector, JitProtoChangeDetector, BindingRecord} +export {DynamicProtoChangeDetector, JitProtoChangeDetector} from './src/change_detection/proto_change_detector'; +export {BindingRecord} + from './src/change_detection/binding_record'; +export {DirectiveRecord} + from './src/change_detection/directive_record'; export {DynamicChangeDetector} from './src/change_detection/dynamic_change_detector'; export {BindingPropagationConfig} diff --git a/modules/angular2/src/change_detection/binding_record.js b/modules/angular2/src/change_detection/binding_record.js new file mode 100644 index 0000000000..7ec5422d51 --- /dev/null +++ b/modules/angular2/src/change_detection/binding_record.js @@ -0,0 +1,58 @@ +import {isPresent, isBlank} from 'angular2/src/facade/lang'; +import {SetterFn} from 'angular2/src/reflection/types'; +import {AST} from './parser/ast'; +import {DirectiveRecord} from './directive_record'; + +const DIRECTIVE="directive"; +const ELEMENT="element"; +const TEXT_NODE="textNode"; + +export class BindingRecord { + mode:string; + ast:AST; + + elementIndex:number; + propertyName:string; + setter:SetterFn; + + directiveRecord:DirectiveRecord; + + constructor(mode:string, ast:AST, elementIndex:number, propertyName:string, setter:SetterFn, directiveRecord:DirectiveRecord) { + this.mode = mode; + this.ast = ast; + + this.elementIndex = elementIndex; + this.propertyName = propertyName; + this.setter = setter; + + this.directiveRecord = directiveRecord; + } + + callOnChange() { + return isPresent(this.directiveRecord) && this.directiveRecord.callOnChange; + } + + isDirective() { + return this.mode === DIRECTIVE; + } + + isElement() { + return this.mode === ELEMENT; + } + + isTextNode() { + return this.mode === TEXT_NODE; + } + + static createForDirective(ast:AST, propertyName:string, setter:SetterFn, directiveRecord:DirectiveRecord) { + return new BindingRecord(DIRECTIVE, ast, 0, propertyName, setter, directiveRecord); + } + + static createForElement(ast:AST, elementIndex:number, propertyName:string) { + return new BindingRecord(ELEMENT, ast, elementIndex, propertyName, null, null); + } + + static createForTextNode(ast:AST, elementIndex:number) { + return new BindingRecord(TEXT_NODE, ast, elementIndex, null, null, null); + } +} \ No newline at end of file diff --git a/modules/angular2/src/change_detection/change_detection_jit_generator.es6 b/modules/angular2/src/change_detection/change_detection_jit_generator.es6 index 80bb346443..e0c8c098ba 100644 --- a/modules/angular2/src/change_detection/change_detection_jit_generator.es6 +++ b/modules/angular2/src/change_detection/change_detection_jit_generator.es6 @@ -3,6 +3,7 @@ import {List, ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/faca import {AbstractChangeDetector} from './abstract_change_detector'; import {ChangeDetectionUtil} from './change_detection_util'; +import {DirectiveRecord} from './directive_record'; import { ProtoRecord, @@ -33,7 +34,7 @@ var UTIL = "ChangeDetectionUtil"; var DISPATCHER_ACCESSOR = "this.dispatcher"; var PIPE_REGISTRY_ACCESSOR = "this.pipeRegistry"; var PROTOS_ACCESSOR = "this.protos"; -var MEMENTOS_ACCESSOR = "this.directiveMementos"; +var DIRECTIVES_ACCESSOR = "this.directiveRecords"; var CONTEXT_ACCESSOR = "this.context"; var CHANGE_LOCAL = "change"; var CHANGES_LOCAL = "changes"; @@ -51,19 +52,19 @@ ${notifyOnAllChangesDone} ${setContext}; return function(dispatcher, pipeRegistry) { - return new ${type}(dispatcher, pipeRegistry, protos, directiveMementos); + return new ${type}(dispatcher, pipeRegistry, protos, directiveRecords); } `; } function constructorTemplate(type:string, fieldsDefinitions:string):string { return ` -var ${type} = function ${type}(dispatcher, pipeRegistry, protos, directiveMementos) { +var ${type} = function ${type}(dispatcher, pipeRegistry, protos, directiveRecords) { ${ABSTRACT_CHANGE_DETECTOR}.call(this); ${DISPATCHER_ACCESSOR} = dispatcher; ${PIPE_REGISTRY_ACCESSOR} = pipeRegistry; ${PROTOS_ACCESSOR} = protos; -${MEMENTOS_ACCESSOR} = directiveMementos; +${DIRECTIVES_ACCESSOR} = directiveRecords; ${LOCALS_ACCESSOR} = null; ${fieldsDefinitions} } @@ -80,7 +81,7 @@ function hydrateTemplate(type:string, mode:string, fieldDefinitions:string, pipe directiveFieldNames:List):string { var directiveInit = ""; for(var i = 0; i < directiveFieldNames.length; ++i) { - directiveInit += `${directiveFieldNames[i]} = this.directiveMementos[${i}].directive(directives);\n`; + directiveInit += `${directiveFieldNames[i]} = directives.directive(this.directiveRecords[${i}]);\n`; } return ` @@ -137,7 +138,7 @@ ${records} } function pipeCheckTemplate(protoIndex:number, context:string, bindingPropagationConfig:string, pipe:string, pipeType:string, - oldValue:string, newValue:string, change:string, invokeMemento:string, + oldValue:string, newValue:string, change:string, update:string, addToChanges, lastInDirective:string):string{ return ` ${CURRENT_PROTO} = ${PROTOS_ACCESSOR}[${protoIndex}]; @@ -151,7 +152,7 @@ if (${pipe} === ${UTIL}.unitialized()) { ${newValue} = ${pipe}.transform(${context}); if (! ${UTIL}.noChangeMarker(${newValue})) { ${change} = true; - ${invokeMemento} + ${update} ${addToChanges} ${oldValue} = ${newValue}; } @@ -160,13 +161,13 @@ ${lastInDirective} } function referenceCheckTemplate(protoIndex:number, assignment:string, oldValue:string, newValue:string, change:string, - invokeMemento:string, addToChanges:string, lastInDirective:string):string { + update:string, addToChanges:string, lastInDirective:string):string { return ` ${CURRENT_PROTO} = ${PROTOS_ACCESSOR}[${protoIndex}]; ${assignment} if (${newValue} !== ${oldValue} || (${newValue} !== ${newValue}) && (${oldValue} !== ${oldValue})) { ${change} = true; - ${invokeMemento} + ${update} ${addToChanges} ${oldValue} = ${newValue}; } @@ -200,7 +201,7 @@ if (${cond}) { } function addToChangesTemplate(oldValue:string, newValue:string):string { - return `${CHANGES_LOCAL} = ${UTIL}.addChange(${CHANGES_LOCAL}, ${CURRENT_PROTO}.bindingMemento, ${UTIL}.simpleChange(${oldValue}, ${newValue}));`; + return `${CHANGES_LOCAL} = ${UTIL}.addChange(${CHANGES_LOCAL}, ${CURRENT_PROTO}.bindingRecord.propertyName, ${UTIL}.simpleChange(${oldValue}, ${newValue}));`; } function updateDirectiveTemplate(oldValue:string, newValue:string, directiveProperty:string):string { @@ -213,7 +214,7 @@ ${directiveProperty} = ${newValue}; function updateElementTemplate(oldValue:string, newValue:string):string { return ` if(throwOnChange) ${UTIL}.throwOnChange(${CURRENT_PROTO}, ${UTIL}.simpleChange(${oldValue}, ${newValue})); -${DISPATCHER_ACCESSOR}.invokeMementoFor(${CURRENT_PROTO}.bindingMemento, ${newValue}); +${DISPATCHER_ACCESSOR}.notifyOnBinding(${CURRENT_PROTO}.bindingRecord, ${newValue}); `; } @@ -230,18 +231,18 @@ if(${CHANGES_LOCAL}) { export class ChangeDetectorJITGenerator { typeName:string; records:List; - directiveMementos:List; + directiveRecords:List; localNames:List; changeNames:List; fieldNames:List; pipeNames:List; changeDetectionStrategy:stirng; - constructor(typeName:string, changeDetectionStrategy:string, records:List, directiveMementos:List) { + constructor(typeName:string, changeDetectionStrategy:string, records:List, directiveRecords:List) { this.typeName = typeName; this.changeDetectionStrategy = changeDetectionStrategy; this.records = records; - this.directiveMementos = directiveMementos; + this.directiveRecords = directiveRecords; this.localNames = this.getLocalNames(records); this.changeNames = this.getChangeNames(this.localNames); @@ -273,8 +274,8 @@ export class ChangeDetectorJITGenerator { generate():Function { var text = typeTemplate(this.typeName, this.genConstructor(), this.genDetectChanges(), this.genCallOnAllChangesDone(), this.genHydrate()); - return new Function('AbstractChangeDetector', 'ChangeDetectionUtil', 'protos', 'directiveMementos', text) - (AbstractChangeDetector, ChangeDetectionUtil, this.records, this.directiveMementos); + return new Function('AbstractChangeDetector', 'ChangeDetectionUtil', 'protos', 'directiveRecords', text) + (AbstractChangeDetector, ChangeDetectionUtil, this.records, this.directiveRecords); } genConstructor():string { @@ -288,11 +289,11 @@ export class ChangeDetectorJITGenerator { } getDirectiveFieldNames():List { - return this.directiveMementos.map((d) => this.getDirective(d)); + return this.directiveRecords.map((d) => this.getDirective(d)); } - getDirective(memento) { - return `this.directive_${memento.name}`; + getDirective(d:DirectiveRecord) { + return `this.directive_${d.name}`; } genFieldDefinitions() { @@ -320,12 +321,12 @@ export class ChangeDetectorJITGenerator { genCallOnAllChangesDone():string { var notifications = []; - var mementos = this.directiveMementos; + var dirs = this.directiveRecords; - for (var i = mementos.length - 1; i >= 0; --i) { - var memento = mementos[i]; - if (memento.callOnAllChangesDone) { - var directive = `this.directive_${memento.name}`; + for (var i = dirs.length - 1; i >= 0; --i) { + var dir = dirs[i]; + if (dir.callOnAllChangesDone) { + var directive = `this.directive_${dir.name}`; notifications.push(onAllChangesDoneTemplate(directive)); } } @@ -363,12 +364,12 @@ export class ChangeDetectorJITGenerator { var pipe = this.pipeNames[r.selfIndex]; var bpc = r.mode === RECORD_TYPE_BINDING_PIPE ? "this.bindingPropagationConfig" : "null"; - var invokeMemento = this.genUpdateDirectiveOrElement(r); + var update = this.genUpdateDirectiveOrElement(r); var addToChanges = this.genAddToChanges(r); var lastInDirective = this.genNotifyOnChanges(r); return pipeCheckTemplate(r.selfIndex - 1, context, bpc, pipe, r.name, oldValue, newValue, change, - invokeMemento, addToChanges, lastInDirective); + update, addToChanges, lastInDirective); } genReferenceCheck(r:ProtoRecord):string { @@ -377,12 +378,12 @@ export class ChangeDetectorJITGenerator { var change = this.changeNames[r.selfIndex]; var assignment = this.genUpdateCurrentValue(r); - var invokeMemento = this.genUpdateDirectiveOrElement(r); + var update = this.genUpdateDirectiveOrElement(r); var addToChanges = this.genAddToChanges(r); var lastInDirective = this.genNotifyOnChanges(r); var check = referenceCheckTemplate(r.selfIndex - 1, assignment, oldValue, newValue, change, - invokeMemento, addToChanges, lastInDirective); + update, addToChanges, lastInDirective); if (r.isPureFunction()) { return this.ifChangedGuard(r, check); } else { @@ -455,8 +456,9 @@ export class ChangeDetectorJITGenerator { var newValue = this.localNames[r.selfIndex]; var oldValue = this.fieldNames[r.selfIndex]; - if (isPresent(r.directiveMemento)) { - var directiveProperty = `${this.getDirective(r.directiveMemento)}.${r.bindingMemento.propertyName}`; + var br = r.bindingRecord; + if (br.isDirective()) { + var directiveProperty = `${this.getDirective(br.directiveRecord)}.${br.propertyName}`; return updateDirectiveTemplate(oldValue, newValue, directiveProperty); } else { return updateElementTemplate(oldValue, newValue); @@ -466,14 +468,13 @@ export class ChangeDetectorJITGenerator { genAddToChanges(r:ProtoRecord):string { var newValue = this.localNames[r.selfIndex]; var oldValue = this.fieldNames[r.selfIndex]; - var callOnChange = r.directiveMemento && r.directiveMemento.callOnChange; - return callOnChange ? addToChangesTemplate(oldValue, newValue) : ""; + return r.bindingRecord.callOnChange() ? addToChangesTemplate(oldValue, newValue) : ""; } genNotifyOnChanges(r:ProtoRecord):string{ - var callOnChange = r.directiveMemento && r.directiveMemento.callOnChange; - if (r.lastInDirective && callOnChange) { - return notifyOnChangesTemplate(this.getDirective(r.directiveMemento)); + var br = r.bindingRecord; + if (r.lastInDirective && br.callOnChange()) { + return notifyOnChangesTemplate(this.getDirective(br.directiveRecord)); } else { return ""; } diff --git a/modules/angular2/src/change_detection/change_detection_util.js b/modules/angular2/src/change_detection/change_detection_util.js index e92643b2fc..ead901dadf 100644 --- a/modules/angular2/src/change_detection/change_detection_util.js +++ b/modules/angular2/src/change_detection/change_detection_util.js @@ -125,11 +125,11 @@ export class ChangeDetectionUtil { return _simpleChange(previousValue, currentValue); } - static addChange(changes, bindingMemento, change){ + static addChange(changes, propertyName:string, change){ if (isBlank(changes)) { changes = {}; } - changes[bindingMemento.propertyName] = change; + changes[propertyName] = change; return changes; } } \ No newline at end of file diff --git a/modules/angular2/src/change_detection/coalesce.js b/modules/angular2/src/change_detection/coalesce.js index a1d0e429de..8c888e6f2a 100644 --- a/modules/angular2/src/change_detection/coalesce.js +++ b/modules/angular2/src/change_detection/coalesce.js @@ -46,8 +46,7 @@ function _selfRecord(r:ProtoRecord, contextIndex:number, selfIndex:number):Proto r.fixedArgs, contextIndex, selfIndex, - r.bindingMemento, - r.directiveMemento, + r.bindingRecord, r.expressionAsString, r.lastInBinding, r.lastInDirective @@ -74,8 +73,7 @@ function _replaceIndices(r:ProtoRecord, selfIndex:number, indexMap:Map) { r.fixedArgs, contextIndex, selfIndex, - r.bindingMemento, - r.directiveMemento, + r.bindingRecord, r.expressionAsString, r.lastInBinding, r.lastInDirective diff --git a/modules/angular2/src/change_detection/directive_record.js b/modules/angular2/src/change_detection/directive_record.js new file mode 100644 index 0000000000..c9715f0abc --- /dev/null +++ b/modules/angular2/src/change_detection/directive_record.js @@ -0,0 +1,19 @@ +export class DirectiveRecord { + elementIndex:number; + directiveIndex:number; + callOnAllChangesDone:boolean; + callOnChange:boolean; + + constructor(elementIndex:number, directiveIndex:number, + callOnAllChangesDone:boolean, + callOnChange:boolean) { + this.elementIndex = elementIndex; + this.directiveIndex = directiveIndex; + this.callOnAllChangesDone = callOnAllChangesDone; + this.callOnChange = callOnChange; + } + + get name() { + return `${this.elementIndex}_${this.directiveIndex}`; + } +} \ No newline at end of file diff --git a/modules/angular2/src/change_detection/dynamic_change_detector.js b/modules/angular2/src/change_detection/dynamic_change_detector.js index 365534d143..af4446fb84 100644 --- a/modules/angular2/src/change_detection/dynamic_change_detector.js +++ b/modules/angular2/src/change_detection/dynamic_change_detector.js @@ -2,6 +2,8 @@ import {isPresent, isBlank, BaseException, FunctionWrapper} from 'angular2/src/f import {List, ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection'; import {AbstractChangeDetector} from './abstract_change_detector'; +import {BindingRecord} from './binding_record'; +import {DirectiveRecord} from './directive_record'; import {PipeRegistry} from './pipes/pipe_registry'; import {ChangeDetectionUtil, uninitialized} from './change_detection_util'; @@ -35,11 +37,11 @@ export class DynamicChangeDetector extends AbstractChangeDetector { protos:List; directives:any; - directiveMementos:List; + directiveRecords:List; changeControlStrategy:string; constructor(changeControlStrategy:string, dispatcher:any, pipeRegistry:PipeRegistry, - protoRecords:List, directiveMementos:List) { + protoRecords:List, directiveRecords:List) { super(); this.dispatcher = dispatcher; this.pipeRegistry = pipeRegistry; @@ -57,7 +59,7 @@ export class DynamicChangeDetector extends AbstractChangeDetector { this.directives = null; this.protos = protoRecords; - this.directiveMementos = directiveMementos; + this.directiveRecords = directiveRecords; this.changeControlStrategy = changeControlStrategy; } @@ -99,45 +101,45 @@ export class DynamicChangeDetector extends AbstractChangeDetector { var change = this._check(proto); if (isPresent(change)) { if (throwOnChange) ChangeDetectionUtil.throwOnChange(proto, change); - this._updateDirectiveOrElement(change, proto.directiveMemento, proto.bindingMemento); - changes = this._addChange(proto.directiveMemento, proto.bindingMemento, change, changes); + this._updateDirectiveOrElement(change, proto.bindingRecord); + changes = this._addChange(proto.bindingRecord, change, changes); } if (proto.lastInDirective && isPresent(changes)) { - this._directive(proto.directiveMemento).onChange(changes); + this._directive(proto.bindingRecord.directiveRecord).onChange(changes); changes = null; } } } callOnAllChangesDone() { - var mementos = this.directiveMementos; - for (var i = mementos.length - 1; i >= 0; --i) { - var memento = mementos[i]; - if (memento.callOnAllChangesDone) { - this._directive(memento).onAllChangesDone(); + var dirs = this.directiveRecords; + for (var i = dirs.length - 1; i >= 0; --i) { + var dir = dirs[i]; + if (dir.callOnAllChangesDone) { + this._directive(dir).onAllChangesDone(); } } } - _updateDirectiveOrElement(change, directiveMemento, bindingMemento) { - if (isBlank(directiveMemento)) { - this.dispatcher.invokeMementoFor(bindingMemento, change.currentValue); + _updateDirectiveOrElement(change, bindingRecord) { + if (isBlank(bindingRecord.directiveRecord)) { + this.dispatcher.notifyOnBinding(bindingRecord, change.currentValue); } else { - bindingMemento.setter(this._directive(directiveMemento), change.currentValue); + bindingRecord.setter(this._directive(bindingRecord.directiveRecord), change.currentValue); } } - _addChange(directiveMemento, bindingMemento, change, changes) { - if (isPresent(directiveMemento) && directiveMemento.callOnChange) { - return ChangeDetectionUtil.addChange(changes, bindingMemento, change); + _addChange(bindingRecord:BindingRecord, change, changes) { + if (bindingRecord.callOnChange()) { + return ChangeDetectionUtil.addChange(changes, bindingRecord.propertyName, change); } else { return changes; } } - _directive(memento) { - return memento.directive(this.directives); + _directive(directive:DirectiveRecord) { + return this.directives.directive(directive); } _check(proto:ProtoRecord) { diff --git a/modules/angular2/src/change_detection/interfaces.js b/modules/angular2/src/change_detection/interfaces.js index 684cd2aeaf..2d9a86eaa7 100644 --- a/modules/angular2/src/change_detection/interfaces.js +++ b/modules/angular2/src/change_detection/interfaces.js @@ -1,11 +1,10 @@ import {List} from 'angular2/src/facade/collection'; import {Locals} from './parser/locals'; -import {AST} from './parser/ast'; import {DEFAULT} from './constants'; +import {BindingRecord} from './binding_record'; export class ProtoChangeDetector { - addAst(ast:AST, bindingMemento:any, directiveMemento:any = null){} - instantiate(dispatcher:any, bindingRecords:List, variableBindings:List, directiveMementos:List):ChangeDetector{ + instantiate(dispatcher:any, bindingRecords:List, variableBindings:List, directiveRecords:List):ChangeDetector{ return null; } } @@ -17,7 +16,7 @@ export class ChangeDetection { } export class ChangeDispatcher { - invokeMementoFor(memento:any, value) {} + notifyOnBinding(bindingRecord:BindingRecord, value:any) {} } export class ChangeDetector { diff --git a/modules/angular2/src/change_detection/proto_change_detector.js b/modules/angular2/src/change_detection/proto_change_detector.js index cb3b9db213..a09cb9369f 100644 --- a/modules/angular2/src/change_detection/proto_change_detector.js +++ b/modules/angular2/src/change_detection/proto_change_detector.js @@ -27,6 +27,7 @@ import {ChangeDetectionUtil} from './change_detection_util'; 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 {coalesce} from './coalesce'; @@ -45,18 +46,6 @@ import { RECORD_TYPE_INTERPOLATE } from './proto_record'; -export class BindingRecord { - ast:AST; - bindingMemento:any; - directiveMemento:any; - - constructor(ast:AST, bindingMemento:any, directiveMemento:any) { - this.ast = ast; - this.bindingMemento = bindingMemento; - this.directiveMemento = directiveMemento; - } -} - export class DynamicProtoChangeDetector extends ProtoChangeDetector { _pipeRegistry:PipeRegistry; _records:List; @@ -68,17 +57,17 @@ export class DynamicProtoChangeDetector extends ProtoChangeDetector { this._changeControlStrategy = changeControlStrategy; } - instantiate(dispatcher:any, bindingRecords:List, variableBindings:List, directiveMementos:List) { + instantiate(dispatcher:any, bindingRecords:List, variableBindings:List, directiveRecords:List) { this._createRecordsIfNecessary(bindingRecords, variableBindings); return new DynamicChangeDetector(this._changeControlStrategy, dispatcher, - this._pipeRegistry, this._records, directiveMementos); + this._pipeRegistry, this._records, directiveRecords); } _createRecordsIfNecessary(bindingRecords:List, variableBindings:List) { if (isBlank(this._records)) { var recordBuilder = new ProtoRecordBuilder(); - ListWrapper.forEach(bindingRecords, (r) => { - recordBuilder.addAst(r.ast, r.bindingMemento, r.directiveMemento, variableBindings); + ListWrapper.forEach(bindingRecords, (b) => { + recordBuilder.addAst(b, variableBindings); }); this._records = coalesce(recordBuilder.records); } @@ -98,22 +87,22 @@ export class JitProtoChangeDetector extends ProtoChangeDetector { this._changeControlStrategy = changeControlStrategy; } - instantiate(dispatcher:any, bindingRecords:List, variableBindings:List, directiveMementos:List) { - this._createFactoryIfNecessary(bindingRecords, variableBindings, directiveMementos); + instantiate(dispatcher:any, bindingRecords:List, variableBindings:List, directiveRecords:List) { + this._createFactoryIfNecessary(bindingRecords, variableBindings, directiveRecords); return this._factory(dispatcher, this._pipeRegistry); } - _createFactoryIfNecessary(bindingRecords:List, variableBindings:List, directiveMementos:List) { + _createFactoryIfNecessary(bindingRecords:List, variableBindings:List, directiveRecords:List) { if (isBlank(this._factory)) { var recordBuilder = new ProtoRecordBuilder(); - ListWrapper.forEach(bindingRecords, (r) => { - recordBuilder.addAst(r.ast, r.bindingMemento, r.directiveMemento, variableBindings); + ListWrapper.forEach(bindingRecords, (b) => { + recordBuilder.addAst(b, variableBindings); }); var c = _jitProtoChangeDetectorClassCounter++; var records = coalesce(recordBuilder.records); var typeName = `ChangeDetector${c}`; this._factory = new ChangeDetectorJITGenerator(typeName, this._changeControlStrategy, records, - directiveMementos).generate(); + directiveRecords).generate(); } } } @@ -125,13 +114,13 @@ class ProtoRecordBuilder { this.records = []; } - addAst(ast:AST, bindingMemento:any, directiveMemento:any = null, variableBindings:List = null) { + addAst(b:BindingRecord, variableBindings:List = null) { var last = ListWrapper.last(this.records); - if (isPresent(last) && last.directiveMemento == directiveMemento) { + if (isPresent(last) && last.bindingRecord.directiveRecord == b.directiveRecord) { last.lastInDirective = false; } - var pr = _ConvertAstIntoProtoRecords.convert(ast, bindingMemento, directiveMemento, this.records.length, variableBindings); + var pr = _ConvertAstIntoProtoRecords.convert(b, this.records.length, variableBindings); if (! ListWrapper.isEmpty(pr)) { var last = ListWrapper.last(pr); last.lastInBinding = true; @@ -144,24 +133,22 @@ class ProtoRecordBuilder { class _ConvertAstIntoProtoRecords { protoRecords:List; - bindingMemento:any; - directiveMemento:any; + bindingRecord:BindingRecord; variableBindings:List; contextIndex:number; expressionAsString:string; - constructor(bindingMemento:any, directiveMemento:any, contextIndex:number, expressionAsString:string, variableBindings:List) { + constructor(bindingRecord:BindingRecord, contextIndex:number, expressionAsString:string, variableBindings:List) { this.protoRecords = []; - this.bindingMemento = bindingMemento; - this.directiveMemento = directiveMemento; + this.bindingRecord = bindingRecord; this.contextIndex = contextIndex; this.expressionAsString = expressionAsString; this.variableBindings = variableBindings; } - static convert(ast:AST, bindingMemento:any, directiveMemento:any, contextIndex:number, variableBindings:List) { - var c = new _ConvertAstIntoProtoRecords(bindingMemento, directiveMemento, contextIndex, ast.toString(), variableBindings); - ast.visit(c); + static convert(b:BindingRecord, contextIndex:number, variableBindings:List) { + var c = new _ConvertAstIntoProtoRecords(b, contextIndex, b.ast.toString(), variableBindings); + b.ast.visit(c); return c.protoRecords; } @@ -262,7 +249,7 @@ class _ConvertAstIntoProtoRecords { var selfIndex = ++ this.contextIndex; ListWrapper.push(this.protoRecords, new ProtoRecord(type, name, funcOrValue, args, fixedArgs, context, selfIndex, - this.bindingMemento, this.directiveMemento, this.expressionAsString, false, false)); + this.bindingRecord, this.expressionAsString, false, false)); return selfIndex; } } diff --git a/modules/angular2/src/change_detection/proto_record.js b/modules/angular2/src/change_detection/proto_record.js index 3b77fca8ac..6f5eb4079f 100644 --- a/modules/angular2/src/change_detection/proto_record.js +++ b/modules/angular2/src/change_detection/proto_record.js @@ -1,4 +1,5 @@ import {List} from 'angular2/src/facade/collection'; +import {BindingRecord} from './binding_record'; export const RECORD_TYPE_SELF = 0; export const RECORD_TYPE_CONST = 1; @@ -20,8 +21,7 @@ export class ProtoRecord { fixedArgs:List; contextIndex:number; selfIndex:number; - bindingMemento:any; - directiveMemento:any; + bindingRecord:BindingRecord; lastInBinding:boolean; lastInDirective:boolean; expressionAsString:string; @@ -33,8 +33,7 @@ export class ProtoRecord { fixedArgs:List, contextIndex:number, selfIndex:number, - bindingMemento:any, - directiveMemento:any, + bindingRecord:BindingRecord, expressionAsString:string, lastInBinding:boolean, lastInDirective:boolean) { @@ -46,8 +45,7 @@ export class ProtoRecord { this.fixedArgs = fixedArgs; this.contextIndex = contextIndex; this.selfIndex = selfIndex; - this.bindingMemento = bindingMemento; - this.directiveMemento = directiveMemento; + this.bindingRecord = bindingRecord; this.lastInBinding = lastInBinding; this.lastInDirective = lastInDirective; this.expressionAsString = expressionAsString; diff --git a/modules/angular2/src/core/compiler/view.js b/modules/angular2/src/core/compiler/view.js index cdb108892a..540030abc7 100644 --- a/modules/angular2/src/core/compiler/view.js +++ b/modules/angular2/src/core/compiler/view.js @@ -1,6 +1,6 @@ import {ListWrapper, MapWrapper, Map, StringMapWrapper, List} from 'angular2/src/facade/collection'; import {AST, Locals, ChangeDispatcher, ProtoChangeDetector, ChangeDetector, - BindingRecord, BindingPropagationConfig, uninitialized} from 'angular2/change_detection'; + ChangeRecord, BindingRecord, DirectiveRecord, BindingPropagationConfig} from 'angular2/change_detection'; import {ProtoElementInjector, ElementInjector, PreBuiltObjects, DirectiveBinding} from './element_injector'; import {ElementBinder} from './element_binder'; @@ -70,11 +70,10 @@ export class View { _setContextAndLocals(newContext, locals) { this.context = newContext; this.locals.parent = locals; - this.changeDetector.hydrate(this.context, this.locals, this.elementInjectors); } _hydrateChangeDetector() { - this.changeDetector.hydrate(this.context, this.locals, this.elementInjectors); + this.changeDetector.hydrate(this.context, this.locals, this); } _dehydrateContext() { @@ -229,18 +228,21 @@ export class View { } // dispatch to element injector or text nodes based on context - invokeMementoFor(memento:any, currentValue:any) { - if (memento instanceof ElementBindingMemento) { - var elementMemento:ElementBindingMemento = memento; + notifyOnBinding(b:BindingRecord, currentValue:any) { + if (b.isElement()) { this.proto.renderer.setElementProperty( - this.render, elementMemento.elementIndex, elementMemento.propertyName, currentValue + this.render, b.elementIndex, b.propertyName, currentValue ); } else { // we know it refers to _textNodes. - var textNodeIndex:number = memento; - this.proto.renderer.setText(this.render, textNodeIndex, currentValue); + this.proto.renderer.setText(this.render, b.elementIndex, currentValue); } } + + directive(directive:DirectiveRecord) { + var elementInjector:ElementInjector = this.elementInjectors[directive.elementIndex]; + return elementInjector.getDirectiveAtIndex(directive.directiveIndex); + } // implementation of EventDispatcher#dispatchEvent dispatchEvent( @@ -277,12 +279,12 @@ export class ProtoView { variableBindings: Map; protoLocals:Map; textNodesWithBindingCount:int; - bindingRecords:List; + bindings:List; parentProtoView:ProtoView; _variableBindings:List; - _directiveMementosMap:Map; - _directiveMementos:List; + _directiveRecordsMap:Map; + _directiveRecords:List; render:renderApi.ProtoViewRef; renderer:renderApi.Renderer; @@ -298,10 +300,10 @@ export class ProtoView { this.protoChangeDetector = protoChangeDetector; this.parentProtoView = null; this.textNodesWithBindingCount = 0; - this.bindingRecords = []; - this._directiveMementosMap = MapWrapper.create(); + this.bindings = []; + this._directiveRecordsMap = MapWrapper.create(); this._variableBindings = null; - this._directiveMementos = null; + this._directiveRecords = null; } //TODO: Tobias or Victor. Moving it into the constructor. @@ -325,23 +327,23 @@ export class ProtoView { //TODO: Tobias or Victor. Moving it into the constructor. // this work should be done the constructor of ProtoView once we separate // ProtoView and ProtoViewBuilder - getDirectiveMementos() { - if (isPresent(this._directiveMementos)) { - return this._directiveMementos; + getdirectiveRecords() { + if (isPresent(this._directiveRecords)) { + return this._directiveRecords; } - this._directiveMementos = []; + 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._directiveMementos, this._getDirectiveMemento(injectorIndex, directiveIndex)); + ListWrapper.push(this._directiveRecords, this._getDirectiveRecord(injectorIndex, directiveIndex)); } } } - return this._directiveMementos; + return this._directiveRecords; } bindVariable(contextName:string, templateName:string) { @@ -361,16 +363,18 @@ export class ProtoView { * Adds a text node binding for the last created ElementBinder via bindElement */ bindTextNode(expression:AST) { - var memento = this.textNodesWithBindingCount++; - ListWrapper.push(this.bindingRecords, new BindingRecord(expression, memento, null)); + 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) { - var memento = new ElementBindingMemento(this.elementBinders.length-1, setterName); - ListWrapper.push(this.bindingRecords, new BindingRecord(expression, memento, null)); + var elementIndex = this.elementBinders.length-1; + var b = BindingRecord.createForElement(expression, elementIndex, setterName); + ListWrapper.push(this.bindings, b); } /** @@ -411,82 +415,22 @@ export class ProtoView { setter:SetterFn) { var elementIndex = this.elementBinders.length-1; - var bindingMemento = new DirectiveBindingMemento( - elementIndex, - directiveIndex, - setterName, - setter - ); - var directiveMemento = this._getDirectiveMemento(elementIndex, directiveIndex); - ListWrapper.push(this.bindingRecords, new BindingRecord(expression, bindingMemento, directiveMemento)); + var directiveRecord = this._getDirectiveRecord(elementIndex, directiveIndex); + var b = BindingRecord.createForDirective(expression, setterName, setter, directiveRecord); + ListWrapper.push(this.bindings, b); } - _getDirectiveMemento(elementInjectorIndex:number, directiveIndex:number) { + _getDirectiveRecord(elementInjectorIndex:number, directiveIndex:number) { var id = elementInjectorIndex * 100 + directiveIndex; var protoElementInjector = this.elementBinders[elementInjectorIndex].protoElementInjector; - if (!MapWrapper.contains(this._directiveMementosMap, id)) { + if (!MapWrapper.contains(this._directiveRecordsMap, id)) { var binding = protoElementInjector.getDirectiveBindingAtIndex(directiveIndex); - MapWrapper.set(this._directiveMementosMap, id, - new DirectiveMemento(elementInjectorIndex, directiveIndex, + MapWrapper.set(this._directiveRecordsMap, id, + new DirectiveRecord(elementInjectorIndex, directiveIndex, binding.callOnAllChangesDone, binding.callOnChange)); } - return MapWrapper.get(this._directiveMementosMap, id); - } -} - -/** - */ -export class ElementBindingMemento { - elementIndex:int; - propertyName:string; - - constructor(elementIndex:int, propertyName:string) { - this.elementIndex = elementIndex; - this.propertyName = propertyName; - } -} - -/** - */ -export class DirectiveBindingMemento { - _elementInjectorIndex:int; - _directiveIndex:int; - propertyName:string; - setter:SetterFn; - constructor( - elementInjectorIndex:number, - directiveIndex:number, - propertyName:string, - setter:SetterFn) { - this._elementInjectorIndex = elementInjectorIndex; - this._directiveIndex = directiveIndex; - this.propertyName = propertyName; - this.setter = setter; - } -} - -class DirectiveMemento { - _elementInjectorIndex:number; - _directiveIndex:number; - callOnAllChangesDone:boolean; - callOnChange:boolean; - - get name() { - return `${this._elementInjectorIndex}_${this._directiveIndex}`; - } - - constructor(elementInjectorIndex:number, directiveIndex:number, callOnAllChangesDone:boolean, - callOnChange:boolean) { - this._elementInjectorIndex = elementInjectorIndex; - this._directiveIndex = directiveIndex; - this.callOnAllChangesDone = callOnAllChangesDone; - this.callOnChange = callOnChange; - } - - directive(elementInjectors:List) { - var elementInjector:ElementInjector = elementInjectors[this._elementInjectorIndex]; - return elementInjector.getDirectiveAtIndex(this._directiveIndex); + return MapWrapper.get(this._directiveRecordsMap, id); } } \ No newline at end of file diff --git a/modules/angular2/src/core/compiler/view_factory.js b/modules/angular2/src/core/compiler/view_factory.js index 083d7b02b8..e897ebea2c 100644 --- a/modules/angular2/src/core/compiler/view_factory.js +++ b/modules/angular2/src/core/compiler/view_factory.js @@ -48,8 +48,8 @@ export class ViewFactory { _createView(protoView:viewModule.ProtoView): viewModule.View { var view = new viewModule.View(protoView, protoView.protoLocals); - var changeDetector = protoView.protoChangeDetector.instantiate(view, protoView.bindingRecords, - protoView.getVariableBindings(), protoView.getDirectiveMementos()); + var changeDetector = protoView.protoChangeDetector.instantiate(view, protoView.bindings, + protoView.getVariableBindings(), protoView.getdirectiveRecords()); var binders = protoView.elementBinders; var elementInjectors = ListWrapper.createFixedSize(binders.length); diff --git a/modules/angular2/test/change_detection/change_detection_spec.js b/modules/angular2/test/change_detection/change_detection_spec.js index 8b6dfc7d91..5b60b8158d 100644 --- a/modules/angular2/test/change_detection/change_detection_spec.js +++ b/modules/angular2/test/change_detection/change_detection_spec.js @@ -7,7 +7,7 @@ import {Parser} from 'angular2/src/change_detection/parser/parser'; import {Lexer} from 'angular2/src/change_detection/parser/lexer'; import {Locals} from 'angular2/src/change_detection/parser/locals'; -import {ChangeDispatcher, DynamicChangeDetector, ChangeDetectionError, BindingRecord, +import {ChangeDispatcher, DynamicChangeDetector, ChangeDetectionError, BindingRecord, DirectiveRecord, PipeRegistry, Pipe, NO_CHANGE, CHECK_ALWAYS, CHECK_ONCE, CHECKED, DETACHED, ON_PUSH, DEFAULT} from 'angular2/change_detection'; import {JitProtoChangeDetector, DynamicProtoChangeDetector} from 'angular2/src/change_detection/proto_change_detector'; @@ -27,6 +27,10 @@ export function main() { return parser.parseBinding(exp, location); } + function dirs(directives:List) { + return new FakeDirectives(directives); + } + function convertLocalsToVariableBindings(locals) { var variableBindings = []; var loc = locals; @@ -37,13 +41,13 @@ export function main() { return variableBindings; } - function createChangeDetector(memo:string, exp:string, context = null, locals = null, registry = null) { + 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 = [new BindingRecord(ast(exp), memo, null)]; + var records = [BindingRecord.createForElement(ast(exp), 0, propName)]; var cd = pcd.instantiate(dispatcher, records, variableBindings, []); cd.hydrate(context, locals, null); @@ -56,9 +60,9 @@ export function main() { return res["dispatcher"].log; } - function instantiate(protoChangeDetector, dispatcher, bindings, directiveMementos = null) { - if (isBlank(directiveMementos)) directiveMementos = []; - return protoChangeDetector.instantiate(dispatcher, bindings, null, directiveMementos); + function instantiate(protoChangeDetector, dispatcher, bindings, directiveRecords = null) { + if (isBlank(directiveRecords)) directiveRecords = []; + return protoChangeDetector.instantiate(dispatcher, bindings, null, directiveRecords); } describe(`${name} change detection`, () => { @@ -204,7 +208,7 @@ export function main() { var pcd = createProtoChangeDetector(); var ast = parser.parseInterpolation("B{{a}}A", "location"); - var cd = instantiate(pcd, dispatcher, [new BindingRecord(ast, "memo", null)]); + var cd = instantiate(pcd, dispatcher, [BindingRecord.createForElement(ast, 0, "memo")]); cd.hydrate(new TestData("value"), null, null); cd.detectChanges(); @@ -241,13 +245,18 @@ export function main() { }); }); - describe("updatingDirectives", () => { - var dirMemento1 = new FakeDirectiveMemento(0, true, true); - var dirMemento2 = new FakeDirectiveMemento(1, true, true); - var dirMementoNoCallbacks = new FakeDirectiveMemento(0, false, false); + describe("updating directives", () => { + var dirRecord1 = new DirectiveRecord(0, 0, true, true); + var dirRecord2 = new DirectiveRecord(0, 1, true, true); + var dirRecordNoCallbacks = new DirectiveRecord(0, 0, false, false); - var updateA = new FakeBindingMemento((o, v) => o.a = v, "a"); - var updateB = new FakeBindingMemento((o, v) => o.b = v, "b"); + function updateA(exp:string, dirRecord) { + return BindingRecord.createForDirective(ast(exp), "a", (o,v) => o.a = v, dirRecord); + } + + function updateB(exp:string, dirRecord) { + return BindingRecord.createForDirective(ast(exp), "b", (o,v) => o.b = v, dirRecord); + } var directive1; var directive2; @@ -260,10 +269,10 @@ export function main() { it("should happen directly, without invoking the dispatcher", () => { var pcd = createProtoChangeDetector(); - var cd = instantiate(pcd, dispatcher, [new BindingRecord(ast("42"), updateA, dirMemento1)], - [dirMemento1]); + var cd = instantiate(pcd, dispatcher, [updateA("42", dirRecord1)], + [dirRecord1]); - cd.hydrate(null, null, [directive1]) + cd.hydrate(null, null, dirs([directive1])); cd.detectChanges(); @@ -276,12 +285,12 @@ export function main() { var pcd = createProtoChangeDetector(); var cd = instantiate(pcd, dispatcher, [ - new BindingRecord(ast("1"), updateA, dirMemento1), - new BindingRecord(ast("2"), updateB, dirMemento1), - new BindingRecord(ast("3"), updateA, dirMemento2) - ], [dirMemento1, dirMemento2]); + updateA("1", dirRecord1), + updateB("2", dirRecord1), + updateA("3", dirRecord2) + ], [dirRecord1, dirRecord2]); - cd.hydrate(null, null, [directive1, directive2]) + cd.hydrate(null, null, dirs([directive1, directive2])); cd.detectChanges(); @@ -293,10 +302,10 @@ export function main() { var pcd = createProtoChangeDetector(); var cd = instantiate(pcd, dispatcher, [ - new BindingRecord(ast("1"), updateA, dirMementoNoCallbacks) - ], [dirMementoNoCallbacks]); + updateA("1", dirRecordNoCallbacks) + ], [dirRecordNoCallbacks]); - cd.hydrate(null, null, [directive1]) + cd.hydrate(null, null, dirs([directive1])); cd.detectChanges(); @@ -308,8 +317,8 @@ export function main() { it("should be called after processing all the children", () => { var pcd = createProtoChangeDetector(); - var cd = instantiate(pcd, dispatcher, [], [dirMemento1, dirMemento2]); - cd.hydrate(null, null, [directive1, directive2]); + var cd = instantiate(pcd, dispatcher, [], [dirRecord1, dirRecord2]); + cd.hydrate(null, null, dirs([directive1, directive2])); cd.detectChanges(); @@ -322,10 +331,10 @@ export function main() { var pcd = createProtoChangeDetector(); var cd = instantiate(pcd, dispatcher, [ - new BindingRecord(ast("1"), updateA, dirMementoNoCallbacks) - ], [dirMementoNoCallbacks]); + updateA("1", dirRecordNoCallbacks) + ], [dirRecordNoCallbacks]); - cd.hydrate(null, null, [directive1]) + cd.hydrate(null, null, dirs([directive1])); cd.detectChanges(); @@ -334,14 +343,14 @@ 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, [], [dirMemento1, dirMemento2]); + var cd = instantiate(pcd, dispatcher, [], [dirRecord1, dirRecord2]); var onChangesDoneCalls = []; var td1; td1 = new TestDirective(() => ListWrapper.push(onChangesDoneCalls, td1)); var td2; td2 = new TestDirective(() => ListWrapper.push(onChangesDoneCalls, td2)); - cd.hydrate(null, null, [td1, td2]); + cd.hydrate(null, null, dirs([td1, td2])); cd.detectChanges(); @@ -352,19 +361,19 @@ export function main() { var pcd = createProtoChangeDetector(); var shadowDomChildPCD = createProtoChangeDetector(); - var parent = pcd.instantiate(dispatcher, [], null, [dirMemento1]); + var parent = pcd.instantiate(dispatcher, [], null, [dirRecord1]); - var child = shadowDomChildPCD.instantiate(dispatcher, [ - new BindingRecord(ast("1"), updateA, dirMemento1)], null, [dirMemento1]); + var child = shadowDomChildPCD.instantiate(dispatcher, + [updateA("1", dirRecord1)], null, [dirRecord1]); parent.addShadowDomChild(child); - var directiveInShadowDOm = new TestDirective(); + var directiveInShadowDom = new TestDirective(); var parentDirective = new TestDirective(() => { - expect(directiveInShadowDOm.a).toBe(null); + expect(directiveInShadowDom.a).toBe(null); }); - parent.hydrate(null, null, [parentDirective]); - child.hydrate(null, null, [directiveInShadowDOm]); + parent.hydrate(null, null, dirs([parentDirective])); + child.hydrate(null, null, dirs([directiveInShadowDom])); parent.detectChanges(); }); @@ -375,11 +384,10 @@ export function main() { describe("enforce no new changes", () => { it("should throw when a record gets changed after it has been checked", () => { var pcd = createProtoChangeDetector(); - pcd.addAst(ast("a"), "a", 1); var dispatcher = new TestDispatcher(); var cd = instantiate(pcd, dispatcher, [ - new BindingRecord(ast("a"), "a", 1) + BindingRecord.createForElement(ast("a"), 0, "a") ]); cd.hydrate(new TestData('value'), null, null); @@ -394,7 +402,7 @@ export function main() { xit("should wrap exceptions into ChangeDetectionError", () => { var pcd = createProtoChangeDetector(); var cd = pcd.instantiate(new TestDispatcher(), [ - new BindingRecord(ast("invalidProp", "someComponent"), "a", 1) + BindingRecord.createForElement(ast("invalidProp"), 0, "a") ], null, []); cd.hydrate(null, null); @@ -836,33 +844,15 @@ class TestData { } } -class FakeDirectiveMemento { - callOnAllChangesDone:boolean; - callOnChange:boolean; - directiveIndex:number; +class FakeDirectives { + directives:List; - constructor(directiveIndex:number = 0, callOnAllChangesDone:boolean = false, callOnChange:boolean = false) { - this.directiveIndex = directiveIndex; - this.callOnAllChangesDone = callOnAllChangesDone; - this.callOnChange = callOnChange; + constructor(directives:List) { + this.directives = directives; } - get name() { - return this.directiveIndex; - } - - directive(directives) { - return directives[this.directiveIndex]; - } -} - -class FakeBindingMemento { - setter:Function; - propertyName:string; - - constructor(setter:Function, propertyName:string) { - this.setter = setter; - this.propertyName = propertyName; + directive(directiveRecord:DirectiveRecord) { + return this.directives[directiveRecord.directiveIndex]; } } @@ -880,8 +870,8 @@ class TestDispatcher extends ChangeDispatcher { this.loggedValues = ListWrapper.create(); } - invokeMementoFor(memento, value) { - ListWrapper.push(this.log, `${memento}=${this._asString(value)}`); + notifyOnBinding(binding, value) { + ListWrapper.push(this.log, `${binding.propertyName}=${this._asString(value)}`); ListWrapper.push(this.loggedValues, value); } diff --git a/modules/angular2/test/change_detection/coalesce_spec.js b/modules/angular2/test/change_detection/coalesce_spec.js index e4d2bc0aca..e67617d3a6 100644 --- a/modules/angular2/test/change_detection/coalesce_spec.js +++ b/modules/angular2/test/change_detection/coalesce_spec.js @@ -6,7 +6,7 @@ import {RECORD_TYPE_SELF, ProtoRecord} from 'angular2/src/change_detection/proto export function main() { function r(funcOrValue, args, contextIndex, selfIndex, lastInBinding = false) { return new ProtoRecord(99, "name", funcOrValue, args, null, contextIndex, selfIndex, - null, null, null, lastInBinding, false); + null, null, lastInBinding, false); } describe("change detection - coalesce", () => { @@ -74,7 +74,7 @@ export function main() { expect(rs[1]).toEqual(new ProtoRecord( RECORD_TYPE_SELF, "self", null, [], null, 1, 2, - null, null, null, + null, null, true, false) ); }); diff --git a/modules/benchmarks/src/change_detection/change_detection_benchmark.js b/modules/benchmarks/src/change_detection/change_detection_benchmark.js index 76a907605e..b4e4c84769 100644 --- a/modules/benchmarks/src/change_detection/change_detection_benchmark.js +++ b/modules/benchmarks/src/change_detection/change_detection_benchmark.js @@ -11,7 +11,8 @@ import { ChangeDetection, dynamicChangeDetection, jitChangeDetection, - BindingRecord + BindingRecord, + DirectiveRecord } from 'angular2/change_detection'; @@ -188,26 +189,26 @@ function setUpChangeDetection(changeDetection:ChangeDetection, iterations, objec var parentProto = changeDetection.createProtoChangeDetector('parent'); var parentCd = parentProto.instantiate(dispatcher, [], [], []); - var targetObj = new Obj(); var proto = changeDetection.createProtoChangeDetector("proto"); - var directiveMemento = new FakeDirectiveMemento("target", targetObj); - var bindingRecords = [ - new BindingRecord(parser.parseBinding('field0', null), new FakeBindingMemento(reflector.setter("field0"), "field0"), directiveMemento), - new BindingRecord(parser.parseBinding('field1', null), new FakeBindingMemento(reflector.setter("field1"), "field1"), directiveMemento), - new BindingRecord(parser.parseBinding('field2', null), new FakeBindingMemento(reflector.setter("field2"), "field2"), directiveMemento), - new BindingRecord(parser.parseBinding('field3', null), new FakeBindingMemento(reflector.setter("field3"), "field3"), directiveMemento), - new BindingRecord(parser.parseBinding('field4', null), new FakeBindingMemento(reflector.setter("field4"), "field4"), directiveMemento), - new BindingRecord(parser.parseBinding('field5', null), new FakeBindingMemento(reflector.setter("field5"), "field5"), directiveMemento), - new BindingRecord(parser.parseBinding('field6', null), new FakeBindingMemento(reflector.setter("field6"), "field6"), directiveMemento), - new BindingRecord(parser.parseBinding('field7', null), new FakeBindingMemento(reflector.setter("field7"), "field7"), directiveMemento), - new BindingRecord(parser.parseBinding('field8', null), new FakeBindingMemento(reflector.setter("field8"), "field8"), directiveMemento), - new BindingRecord(parser.parseBinding('field9', null), new FakeBindingMemento(reflector.setter("field9"), "field9"), directiveMemento) + var directiveRecord = new DirectiveRecord(0, 0, false, false); + var bindings = [ + BindingRecord.createForDirective(parser.parseBinding('field0', null), "field0", reflector.setter("field0"), directiveRecord), + BindingRecord.createForDirective(parser.parseBinding('field1', null), "field1", reflector.setter("field1"), directiveRecord), + BindingRecord.createForDirective(parser.parseBinding('field2', null), "field2", reflector.setter("field2"), directiveRecord), + BindingRecord.createForDirective(parser.parseBinding('field3', null), "field3", reflector.setter("field3"), directiveRecord), + BindingRecord.createForDirective(parser.parseBinding('field4', null), "field4", reflector.setter("field4"), directiveRecord), + BindingRecord.createForDirective(parser.parseBinding('field5', null), "field5", reflector.setter("field5"), directiveRecord), + BindingRecord.createForDirective(parser.parseBinding('field6', null), "field6", reflector.setter("field6"), directiveRecord), + BindingRecord.createForDirective(parser.parseBinding('field7', null), "field7", reflector.setter("field7"), directiveRecord), + BindingRecord.createForDirective(parser.parseBinding('field8', null), "field8", reflector.setter("field8"), directiveRecord), + BindingRecord.createForDirective(parser.parseBinding('field9', null), "field9", reflector.setter("field9"), directiveRecord) ]; + var targetObj = new Obj(); for (var i = 0; i < iterations; ++i) { - var cd = proto.instantiate(dispatcher, bindingRecords, [], [directiveMemento]); - cd.hydrate(object, null, null); + var cd = proto.instantiate(dispatcher, bindings, [], [directiveRecord]); + cd.hydrate(object, null, new FakeDirectives(targetObj)); parentCd.addChild(cd); } return parentCd; @@ -298,36 +299,20 @@ export function main () { } } -class FakeBindingMemento { - setter:Function; - propertyName:string; - - constructor(setter:Function, propertyName:string) { - this.setter = setter; - this.propertyName = propertyName; - } -} - -class FakeDirectiveMemento { +class FakeDirectives { targetObj:Obj; - name:string; - callOnChange:boolean; - callOnAllChangesDone:boolean; - constructor(name, targetObj) { + constructor(targetObj) { this.targetObj = targetObj; - this.name = name; - this.callOnChange = false; - this.callOnAllChangesDone = false; } - directive(dirs) { + directive(record) { return this.targetObj; } } class DummyDispatcher extends ChangeDispatcher { - invokeMementoFor(bindingMemento, newValue) { + notifyOnBinding(bindingRecord, newValue) { throw "Should not be used"; } }