fix(cd): report all changes on first cd run
- null values would not have been reported for Dart - undefined values would not have been reported for JS Closes #454
This commit is contained in:
parent
829c28f3ee
commit
b734d56b83
|
@ -21,6 +21,8 @@ import {
|
|||
import {ChangeDetector, ChangeRecord, ChangeDispatcher} from './interfaces';
|
||||
import {ExpressionChangedAfterItHasBeenChecked, ChangeDetectionError} from './exceptions';
|
||||
|
||||
var _uninitialized = new Object();
|
||||
|
||||
class SimpleChange {
|
||||
previousValue:any;
|
||||
currentValue:any;
|
||||
|
@ -43,6 +45,7 @@ export class DynamicChangeDetector extends ChangeDetector {
|
|||
this.dispatcher = dispatcher;
|
||||
this.formatters = formatters;
|
||||
this.values = ListWrapper.createFixedSize(protoRecords.length + 1);
|
||||
ListWrapper.fill(this.values, _uninitialized);
|
||||
this.protos = protoRecords;
|
||||
|
||||
this.children = [];
|
||||
|
@ -123,10 +126,9 @@ export class DynamicChangeDetector extends ChangeDetector {
|
|||
var prevValue = this._readSelf(proto);
|
||||
var currValue = this._calculateCurrValue(proto);
|
||||
|
||||
if (! isSame(prevValue, currValue)) {
|
||||
if (!isSame(prevValue, currValue)) {
|
||||
this._writeSelf(proto, currValue);
|
||||
return new SimpleChange(prevValue, currValue);
|
||||
|
||||
return new SimpleChange(prevValue === _uninitialized ? null : prevValue, currValue);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
@ -174,7 +176,7 @@ export class DynamicChangeDetector extends ChangeDetector {
|
|||
var self = this._readSelf(proto);
|
||||
var context = this._readContext(proto);
|
||||
|
||||
if (isBlank(self)) {
|
||||
if (isBlank(self) || self === _uninitialized) {
|
||||
if (ArrayChanges.supports(context)) {
|
||||
self = new ArrayChanges();
|
||||
} else if (KeyValueChanges.supports(context)) {
|
||||
|
|
|
@ -57,6 +57,16 @@ export function main() {
|
|||
expect(dispatcher.log).toEqual(['name=Misko']);
|
||||
});
|
||||
|
||||
it('should report all changes on the first run including uninitialized values', () => {
|
||||
var uninit = new Uninitialized();
|
||||
var c = createChangeDetector('value', 'value', uninit);
|
||||
var cd = c["changeDetector"];
|
||||
var dispatcher = c["dispatcher"];
|
||||
|
||||
cd.detectChanges();
|
||||
expect(dispatcher.log).toEqual(['value=null']);
|
||||
});
|
||||
|
||||
it("should support literals", () => {
|
||||
expect(executeWatch('const', '10')).toEqual(['const=10']);
|
||||
expect(executeWatch('const', '"str"')).toEqual(['const=str']);
|
||||
|
@ -237,10 +247,10 @@ export function main() {
|
|||
pcd.addAst(ast('invalidProp', 'someComponent'), "a", 1);
|
||||
|
||||
var cd = pcd.instantiate(new TestDispatcher(), null);
|
||||
cd.setContext(null);
|
||||
|
||||
try {
|
||||
cd.detectChanges();
|
||||
|
||||
throw new BaseException("fail");
|
||||
} catch (e) {
|
||||
expect(e).toBeAnInstanceOf(ChangeDetectionError);
|
||||
|
@ -430,6 +440,10 @@ class Address {
|
|||
}
|
||||
}
|
||||
|
||||
class Uninitialized {
|
||||
value:any;
|
||||
}
|
||||
|
||||
class TestData {
|
||||
a;
|
||||
|
||||
|
@ -474,4 +488,4 @@ class TestDispatcher extends ChangeDispatcher {
|
|||
_asString(value) {
|
||||
return (isBlank(value) ? 'null' : value.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ library facade.collection;
|
|||
|
||||
import 'dart:collection' show HashMap, IterableBase, Iterator;
|
||||
export 'dart:core' show Map, List, Set;
|
||||
import 'dart:math' show max, min;
|
||||
|
||||
class MapIterator extends Iterator<List> {
|
||||
Iterator _iterator;
|
||||
|
@ -105,6 +106,18 @@ class ListWrapper {
|
|||
static void clear(List l) { l.clear(); }
|
||||
static String join(List l, String s) => l.join(s);
|
||||
static bool isEmpty(list) => list.isEmpty;
|
||||
static void fill(List l, value, [int start = 0, int end]) {
|
||||
// JS semantics
|
||||
// see https://github.com/google/traceur-compiler/blob/81880cd3f17bac7de90a4cd0339e9f1a9f61d24c/src/runtime/polyfills/Array.js#L94
|
||||
int len = l.length;
|
||||
start = start < 0 ? max(len + start, 0) : min(start, len);
|
||||
if (end == null) {
|
||||
end = len;
|
||||
} else {
|
||||
end = end < 0 ? max(len + end, 0) : min(end, len);
|
||||
}
|
||||
l.fillRange(start, end, value);
|
||||
}
|
||||
}
|
||||
|
||||
bool isListLikeIterable(obj) => obj is Iterable;
|
||||
|
|
|
@ -166,6 +166,9 @@ export class ListWrapper {
|
|||
static isEmpty(list) {
|
||||
return list.length == 0;
|
||||
}
|
||||
static fill(list:List, value, start:int = 0, end:int = undefined) {
|
||||
list.fill(value, start, end);
|
||||
}
|
||||
}
|
||||
|
||||
export function isListLikeIterable(obj):boolean {
|
||||
|
|
Loading…
Reference in New Issue