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