Skip to content

Commit b734d56

Browse files
vicbmhevery
authored andcommitted
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 angular#454
1 parent 829c28f commit b734d56

File tree

4 files changed

+38
-6
lines changed

4 files changed

+38
-6
lines changed

modules/change_detection/src/dynamic_change_detector.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import {
2121
import {ChangeDetector, ChangeRecord, ChangeDispatcher} from './interfaces';
2222
import {ExpressionChangedAfterItHasBeenChecked, ChangeDetectionError} from './exceptions';
2323

24+
var _uninitialized = new Object();
25+
2426
class SimpleChange {
2527
previousValue:any;
2628
currentValue:any;
@@ -43,6 +45,7 @@ export class DynamicChangeDetector extends ChangeDetector {
4345
this.dispatcher = dispatcher;
4446
this.formatters = formatters;
4547
this.values = ListWrapper.createFixedSize(protoRecords.length + 1);
48+
ListWrapper.fill(this.values, _uninitialized);
4649
this.protos = protoRecords;
4750

4851
this.children = [];
@@ -123,10 +126,9 @@ export class DynamicChangeDetector extends ChangeDetector {
123126
var prevValue = this._readSelf(proto);
124127
var currValue = this._calculateCurrValue(proto);
125128

126-
if (! isSame(prevValue, currValue)) {
129+
if (!isSame(prevValue, currValue)) {
127130
this._writeSelf(proto, currValue);
128-
return new SimpleChange(prevValue, currValue);
129-
131+
return new SimpleChange(prevValue === _uninitialized ? null : prevValue, currValue);
130132
} else {
131133
return null;
132134
}
@@ -174,7 +176,7 @@ export class DynamicChangeDetector extends ChangeDetector {
174176
var self = this._readSelf(proto);
175177
var context = this._readContext(proto);
176178

177-
if (isBlank(self)) {
179+
if (isBlank(self) || self === _uninitialized) {
178180
if (ArrayChanges.supports(context)) {
179181
self = new ArrayChanges();
180182
} else if (KeyValueChanges.supports(context)) {

modules/change_detection/test/change_detection_spec.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,16 @@ export function main() {
5757
expect(dispatcher.log).toEqual(['name=Misko']);
5858
});
5959

60+
it('should report all changes on the first run including uninitialized values', () => {
61+
var uninit = new Uninitialized();
62+
var c = createChangeDetector('value', 'value', uninit);
63+
var cd = c["changeDetector"];
64+
var dispatcher = c["dispatcher"];
65+
66+
cd.detectChanges();
67+
expect(dispatcher.log).toEqual(['value=null']);
68+
});
69+
6070
it("should support literals", () => {
6171
expect(executeWatch('const', '10')).toEqual(['const=10']);
6272
expect(executeWatch('const', '"str"')).toEqual(['const=str']);
@@ -237,10 +247,10 @@ export function main() {
237247
pcd.addAst(ast('invalidProp', 'someComponent'), "a", 1);
238248

239249
var cd = pcd.instantiate(new TestDispatcher(), null);
250+
cd.setContext(null);
240251

241252
try {
242253
cd.detectChanges();
243-
244254
throw new BaseException("fail");
245255
} catch (e) {
246256
expect(e).toBeAnInstanceOf(ChangeDetectionError);
@@ -430,6 +440,10 @@ class Address {
430440
}
431441
}
432442

443+
class Uninitialized {
444+
value:any;
445+
}
446+
433447
class TestData {
434448
a;
435449

@@ -474,4 +488,4 @@ class TestDispatcher extends ChangeDispatcher {
474488
_asString(value) {
475489
return (isBlank(value) ? 'null' : value.toString());
476490
}
477-
}
491+
}

modules/facade/src/collection.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ library facade.collection;
22

33
import 'dart:collection' show HashMap, IterableBase, Iterator;
44
export 'dart:core' show Map, List, Set;
5+
import 'dart:math' show max, min;
56

67
class MapIterator extends Iterator<List> {
78
Iterator _iterator;
@@ -105,6 +106,18 @@ class ListWrapper {
105106
static void clear(List l) { l.clear(); }
106107
static String join(List l, String s) => l.join(s);
107108
static bool isEmpty(list) => list.isEmpty;
109+
static void fill(List l, value, [int start = 0, int end]) {
110+
// JS semantics
111+
// see https://github.com/google/traceur-compiler/blob/81880cd3f17bac7de90a4cd0339e9f1a9f61d24c/src/runtime/polyfills/Array.js#L94
112+
int len = l.length;
113+
start = start < 0 ? max(len + start, 0) : min(start, len);
114+
if (end == null) {
115+
end = len;
116+
} else {
117+
end = end < 0 ? max(len + end, 0) : min(end, len);
118+
}
119+
l.fillRange(start, end, value);
120+
}
108121
}
109122

110123
bool isListLikeIterable(obj) => obj is Iterable;

modules/facade/src/collection.es6

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ export class ListWrapper {
166166
static isEmpty(list) {
167167
return list.length == 0;
168168
}
169+
static fill(list:List, value, start:int = 0, end:int = undefined) {
170+
list.fill(value, start, end);
171+
}
169172
}
170173

171174
export function isListLikeIterable(obj):boolean {

0 commit comments

Comments
 (0)