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 {ChangeDetector, ChangeRecord, ChangeDispatcher} from './interfaces';
|
||||||
import {ExpressionChangedAfterItHasBeenChecked, ChangeDetectionError} from './exceptions';
|
import {ExpressionChangedAfterItHasBeenChecked, ChangeDetectionError} from './exceptions';
|
||||||
|
|
||||||
|
var _uninitialized = new Object();
|
||||||
|
|
||||||
class SimpleChange {
|
class SimpleChange {
|
||||||
previousValue:any;
|
previousValue:any;
|
||||||
currentValue:any;
|
currentValue:any;
|
||||||
|
@ -43,6 +45,7 @@ export class DynamicChangeDetector extends ChangeDetector {
|
||||||
this.dispatcher = dispatcher;
|
this.dispatcher = dispatcher;
|
||||||
this.formatters = formatters;
|
this.formatters = formatters;
|
||||||
this.values = ListWrapper.createFixedSize(protoRecords.length + 1);
|
this.values = ListWrapper.createFixedSize(protoRecords.length + 1);
|
||||||
|
ListWrapper.fill(this.values, _uninitialized);
|
||||||
this.protos = protoRecords;
|
this.protos = protoRecords;
|
||||||
|
|
||||||
this.children = [];
|
this.children = [];
|
||||||
|
@ -123,10 +126,9 @@ export class DynamicChangeDetector extends ChangeDetector {
|
||||||
var prevValue = this._readSelf(proto);
|
var prevValue = this._readSelf(proto);
|
||||||
var currValue = this._calculateCurrValue(proto);
|
var currValue = this._calculateCurrValue(proto);
|
||||||
|
|
||||||
if (! isSame(prevValue, currValue)) {
|
if (!isSame(prevValue, currValue)) {
|
||||||
this._writeSelf(proto, currValue);
|
this._writeSelf(proto, currValue);
|
||||||
return new SimpleChange(prevValue, currValue);
|
return new SimpleChange(prevValue === _uninitialized ? null : prevValue, currValue);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -174,7 +176,7 @@ export class DynamicChangeDetector extends ChangeDetector {
|
||||||
var self = this._readSelf(proto);
|
var self = this._readSelf(proto);
|
||||||
var context = this._readContext(proto);
|
var context = this._readContext(proto);
|
||||||
|
|
||||||
if (isBlank(self)) {
|
if (isBlank(self) || self === _uninitialized) {
|
||||||
if (ArrayChanges.supports(context)) {
|
if (ArrayChanges.supports(context)) {
|
||||||
self = new ArrayChanges();
|
self = new ArrayChanges();
|
||||||
} else if (KeyValueChanges.supports(context)) {
|
} else if (KeyValueChanges.supports(context)) {
|
||||||
|
|
|
@ -57,6 +57,16 @@ export function main() {
|
||||||
expect(dispatcher.log).toEqual(['name=Misko']);
|
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", () => {
|
it("should support literals", () => {
|
||||||
expect(executeWatch('const', '10')).toEqual(['const=10']);
|
expect(executeWatch('const', '10')).toEqual(['const=10']);
|
||||||
expect(executeWatch('const', '"str"')).toEqual(['const=str']);
|
expect(executeWatch('const', '"str"')).toEqual(['const=str']);
|
||||||
|
@ -237,10 +247,10 @@ export function main() {
|
||||||
pcd.addAst(ast('invalidProp', 'someComponent'), "a", 1);
|
pcd.addAst(ast('invalidProp', 'someComponent'), "a", 1);
|
||||||
|
|
||||||
var cd = pcd.instantiate(new TestDispatcher(), null);
|
var cd = pcd.instantiate(new TestDispatcher(), null);
|
||||||
|
cd.setContext(null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cd.detectChanges();
|
cd.detectChanges();
|
||||||
|
|
||||||
throw new BaseException("fail");
|
throw new BaseException("fail");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
expect(e).toBeAnInstanceOf(ChangeDetectionError);
|
expect(e).toBeAnInstanceOf(ChangeDetectionError);
|
||||||
|
@ -430,6 +440,10 @@ class Address {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Uninitialized {
|
||||||
|
value:any;
|
||||||
|
}
|
||||||
|
|
||||||
class TestData {
|
class TestData {
|
||||||
a;
|
a;
|
||||||
|
|
||||||
|
@ -474,4 +488,4 @@ class TestDispatcher extends ChangeDispatcher {
|
||||||
_asString(value) {
|
_asString(value) {
|
||||||
return (isBlank(value) ? 'null' : value.toString());
|
return (isBlank(value) ? 'null' : value.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ library facade.collection;
|
||||||
|
|
||||||
import 'dart:collection' show HashMap, IterableBase, Iterator;
|
import 'dart:collection' show HashMap, IterableBase, Iterator;
|
||||||
export 'dart:core' show Map, List, Set;
|
export 'dart:core' show Map, List, Set;
|
||||||
|
import 'dart:math' show max, min;
|
||||||
|
|
||||||
class MapIterator extends Iterator<List> {
|
class MapIterator extends Iterator<List> {
|
||||||
Iterator _iterator;
|
Iterator _iterator;
|
||||||
|
@ -105,6 +106,18 @@ class ListWrapper {
|
||||||
static void clear(List l) { l.clear(); }
|
static void clear(List l) { l.clear(); }
|
||||||
static String join(List l, String s) => l.join(s);
|
static String join(List l, String s) => l.join(s);
|
||||||
static bool isEmpty(list) => list.isEmpty;
|
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;
|
bool isListLikeIterable(obj) => obj is Iterable;
|
||||||
|
|
|
@ -166,6 +166,9 @@ export class ListWrapper {
|
||||||
static isEmpty(list) {
|
static isEmpty(list) {
|
||||||
return list.length == 0;
|
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 {
|
export function isListLikeIterable(obj):boolean {
|
||||||
|
|
Loading…
Reference in New Issue