refactor(change_detection): removed directive and binding mementos

This commit is contained in:
vsavkin 2015-04-09 07:57:33 -07:00
parent 5408a9a72d
commit 61cb99ea42
15 changed files with 291 additions and 306 deletions

View File

@ -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}

View File

@ -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);
}
}

View File

@ -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>):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<ProtoRecord>;
directiveMementos:List;
directiveRecords:List;
localNames:List<string>;
changeNames:List<string>;
fieldNames:List<string>;
pipeNames:List<string>;
changeDetectionStrategy:stirng;
constructor(typeName:string, changeDetectionStrategy:string, records:List<ProtoRecord>, directiveMementos:List) {
constructor(typeName:string, changeDetectionStrategy:string, records:List<ProtoRecord>, 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<string> {
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 "";
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -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}`;
}
}

View File

@ -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<ProtoRecord>;
directives:any;
directiveMementos:List;
directiveRecords:List;
changeControlStrategy:string;
constructor(changeControlStrategy:string, dispatcher:any, pipeRegistry:PipeRegistry,
protoRecords:List<ProtoRecord>, directiveMementos:List) {
protoRecords:List<ProtoRecord>, 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) {

View File

@ -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 {

View File

@ -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<ProtoRecord>;
@ -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;
}
}

View File

@ -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;

View File

@ -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<ElementInjector>) {
var elementInjector:ElementInjector = elementInjectors[this._elementInjectorIndex];
return elementInjector.getDirectiveAtIndex(this._directiveIndex);
return MapWrapper.get(this._directiveRecordsMap, id);
}
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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)
);
});

View File

@ -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";
}
}