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:
Victor Berchet 2015-01-22 11:52:36 +01:00 committed by Misko Hevery
parent 829c28f3ee
commit b734d56b83
4 changed files with 38 additions and 6 deletions

View File

@ -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 = [];
@ -125,8 +128,7 @@ export class DynamicChangeDetector extends ChangeDetector {
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)) {

View File

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

View File

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

View File

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