Skip to content
This repository has been archived by the owner on Feb 22, 2018. It is now read-only.

Commit

Permalink
fix(change-detection): delay processing watch registration inside rea…
Browse files Browse the repository at this point in the history
…ction fn.

If a reaction function registers a new watch that watch should not be processed 
until the next change detection cycle.
  • Loading branch information
mhevery committed Mar 5, 2014
1 parent 3a92ac0 commit cd4e2e3
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 2 deletions.
2 changes: 1 addition & 1 deletion lib/change_detection/watch_group.dart
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,7 @@ class RootWatchGroup extends WatchGroup {
int count = 0;
if (processStopwatch != null) processStopwatch.stop();
Watch dirtyWatch = _dirtyWatchHead;
_dirtyWatchHead = _dirtyWatchTail = null;
RootWatchGroup root = _rootGroup;
root._removeCount = 0;
while(dirtyWatch != null) {
Expand All @@ -421,7 +422,6 @@ class RootWatchGroup extends WatchGroup {
dirtyWatch._nextDirtyWatch = null;
dirtyWatch = nextDirtyWatch;
}
_dirtyWatchHead = _dirtyWatchTail = null;
if (processStopwatch != null) processStopwatch..stop()..increment(count);
return count;
}
Expand Down
26 changes: 25 additions & 1 deletion test/change_detection/watch_group_spec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ void main() {

// obj, arg0, arg1;
expect(watchGrp.fieldCost).toEqual(3);
// methodA(), mothodA()
// methodA(), methodA()
expect(watchGrp.evalCost).toEqual(2);

watchGrp.detectChanges();
Expand Down Expand Up @@ -423,6 +423,30 @@ void main() {
expect(logger).toEqual([]);
});

it('should not return null when evaling method first time', () {
context['text'] ='abc';
var ast = new MethodAST(parse('text'), 'toUpperCase', []);
var watch = watchGrp.watch(ast, (v, p) => logger(v));

watchGrp.detectChanges();
expect(logger).toEqual(['ABC']);
});

it('should not eval a function if registered during reaction', () {
context['text'] ='abc';
var ast = new MethodAST(parse('text'), 'toLowerCase', []);
var watch = watchGrp.watch(ast, (v, p) {
var ast = new MethodAST(parse('text'), 'toUpperCase', []);
watchGrp.watch(ast, (v, p) {
logger(v);
});
});

watchGrp.detectChanges();
watchGrp.detectChanges();
expect(logger).toEqual(['ABC']);
});

it('should read connstant', () {
// should fire on initial adding
expect(watchGrp.fieldCost).toEqual(0);
Expand Down
33 changes: 33 additions & 0 deletions test/core/scope_spec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1189,6 +1189,39 @@ void main() {
}));


it('should properly watch array of fields', inject((RootScope rootScope, Logger log) {
rootScope.context['foo'] = () => 12;
rootScope.watch('foo()', (v, o) => log(v));
expect(log).toEqual([]);
rootScope.apply();
expect(log).toEqual([12]);
}));


it('should properly watch array of fields', inject((RootScope rootScope, Logger log) {
rootScope.context['foo'] = 'abc';
rootScope.watch('foo.contains("b")', (v, o) => log([v, o]));
expect(log).toEqual([]);
rootScope.apply();
expect(log).toEqual([[true, null]]);
log.clear();
}));


it('should not trigger new watcher in the flush where it was added', inject((Scope scope) {
var log = [] ;
scope.context['foo'] = () => 'foo';
scope.watch('1', (value, __) {
expect(value).toEqual(1);
scope.watch('foo()', (value, __) {
log.add(value);
});
});
scope.apply();
expect(log).toEqual(['foo']);
}));


it('should properly watch array of fields2', inject((RootScope rootScope, Logger log) {
rootScope.watch('[ctrl.foo, ctrl.bar]', (v, o) => log([v, o]));
expect(log).toEqual([]);
Expand Down

0 comments on commit cd4e2e3

Please sign in to comment.