feat(ChangeDetector): implement enabling/disabling records

This commit is contained in:
vsavkin
2014-11-14 15:35:41 -08:00
parent 8dfbc242af
commit daf8f72b74
5 changed files with 238 additions and 26 deletions

View File

@ -1,6 +1,6 @@
import {ProtoWatchGroup, WatchGroup} from './watch_group';
import {ProtoRecord, Record} from './record';
import {FIELD, int} from 'facade/lang';
import {FIELD, int, isPresent} from 'facade/lang';
export * from './record';
export * from './watch_group'
@ -12,11 +12,10 @@ export class ChangeDetector {
}
detectChanges():int {
var record:Record = this._rootWatchGroup.headRecord;
var count:int = 0;
for (record = this._rootWatchGroup.headRecord;
record != null;
record = record.next) {
for (var record = this._rootWatchGroup.headEnabledRecord;
isPresent(record);
record = record.nextEnabled) {
if (record.check()) {
count++;
}

View File

@ -65,6 +65,12 @@ export class Record {
@FIELD('final protoRecord:ProtoRecord')
@FIELD('next:Record')
@FIELD('prev:Record')
/// This reference can change.
@FIELD('nextEnabled:Record')
/// This reference can change.
@FIELD('prevEnabled:Record')
@FIELD('dest:Record')
@FIELD('previousValue')
@ -86,6 +92,9 @@ export class Record {
this.next = null;
this.prev = null;
this.nextEnabled = null;
this.prevEnabled = null;
this.disabled = false;
this.dest = null;
this.previousValue = null;
@ -163,9 +172,11 @@ export class Record {
return FunctionWrapper.apply(this.context, this.args);
case MODE_STATE_INVOKE_PURE_FUNCTION:
this.watchGroup.disableRecord(this);
return FunctionWrapper.apply(this.funcOrValue, this.args);
case MODE_STATE_CONST:
this.watchGroup.disableRecord(this);
return this.funcOrValue;
case MODE_STATE_MARKER:
@ -184,10 +195,12 @@ export class Record {
updateArg(value, position:int) {
this.args[position] = value;
this.watchGroup.enableRecord(this);
}
updateContext(value) {
this.context = value;
this.watchGroup.enableRecord(this);
}
}

View File

@ -56,21 +56,11 @@ export class ProtoWatchGroup {
}
_createRecords(watchGroup:WatchGroup, formatters:Map) {
var tail, prevRecord;
watchGroup.headRecord = tail = new Record(watchGroup, this.headRecord, formatters);
this.headRecord.recordInConstruction = watchGroup.headRecord;
for (var proto = this.headRecord.next; proto != null; proto = proto.next) {
prevRecord = tail;
tail = new Record(watchGroup, proto, formatters);
proto.recordInConstruction = tail;
tail.prev = prevRecord;
prevRecord.next = tail;
for (var proto = this.headRecord; proto != null; proto = proto.next) {
var record = new Record(watchGroup, proto, formatters);
proto.recordInConstruction = record;
watchGroup.addRecord(record);
}
watchGroup.tailRecord = tail;
}
_setDestination() {
@ -95,9 +85,70 @@ export class WatchGroup {
this.dispatcher = dispatcher;
this.headRecord = null;
this.tailRecord = null;
this.headEnabledRecord = null;
this.tailEnabledRecord = null;
this.context = null;
}
addRecord(record:Record) {
if (isPresent(this.tailRecord)) {
this.tailRecord.next = record;
this.tailRecord.nextEnabled = record;
record.prev = this.tailRecord;
record.prevEnabled = this.tailRecord;
this.tailRecord = this.tailEnabledRecord = record;
} else {
this.headRecord = this.tailRecord = record;
this.headEnabledRecord = this.tailEnabledRecord = record;
}
}
disableRecord(record:Record) {
var prev = record.prevEnabled;
var next = record.nextEnabled;
record.disabled = true;
if (isPresent(prev)) {
prev.nextEnabled = next;
} else {
this.headEnabledRecord = next;
}
if (isPresent(next)) {
next.prevEnabled = prev;
} else {
this.tailEnabledRecord = prev;
}
}
enableRecord(record:Record) {
if (!record.disabled) return;
var prev = record.prev;
while (prev != null && prev.disabled) prev = prev.prev;
var next = record.next;
while (next != null && next.disabled) next = next.next;
record.disabled = false;
record.prevEnabled = prev;
record.nextEnabled = next;
if (isPresent(prev)) {
prev.nextEnabled = record;
} else {
this.headEnabledRecord = record;
}
if (isPresent(next)) {
next.prevEnabled = record;
} else {
this.tailEnabledRecord = record;
}
}
insertChildGroup(newChild:WatchGroup, insertAfter:WatchGroup) {
throw 'not implemented';
}