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

Commit

Permalink
fix(scope): Use runAsync for microtasks in digest.
Browse files Browse the repository at this point in the history
BREAKING CHANGE:

Microtasks scheduled in flush will process in current cycle, but they 
are not allowed to do model changes.

Microtasks scheduled in digest will be executed in digest, counting
towards the ScopeDigestTTL.
  • Loading branch information
jbdeboer authored and chirayuk committed Jun 11, 2014
1 parent 81667aa commit d1e745e
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 16 deletions.
35 changes: 22 additions & 13 deletions lib/core/scope.dart
Original file line number Diff line number Diff line change
Expand Up @@ -680,15 +680,8 @@ class RootScope extends Scope {
ChangeLog changeLog;
_scopeStats.digestStart();
do {
while (_runAsyncHead != null) {
try {
_runAsyncHead.fn();
} catch (e, s) {
_exceptionHandler(e, s);
}
_runAsyncHead = _runAsyncHead._next;
}
_runAsyncTail = null;

int asyncCount = _runAsyncFns();

digestTTL--;
count = rootWatchGroup.detectChanges(
Expand All @@ -704,7 +697,7 @@ class RootScope extends Scope {
digestLog = [];
changeLog = (e, c, p) => digestLog.add('$e: $c <= $p');
} else {
log.add(digestLog.join(', '));
log.add("${asyncCount > 0 ? 'async:$asyncCount' : ''}${digestLog.join(', ')}");
digestLog.clear();
}
}
Expand All @@ -713,7 +706,7 @@ class RootScope extends Scope {
'Last $LOG_COUNT iterations:\n${log.join('\n')}';
}
_scopeStats.digestLoop(count);
} while (count > 0);
} while (count > 0 || _runAsyncHead != null);
} finally {
_scopeStats.digestEnd();
_transitionState(STATE_DIGEST, null);
Expand Down Expand Up @@ -756,7 +749,8 @@ class RootScope extends Scope {
if (_domReadHead == null) _stats.domReadEnd();
}
_domReadTail = null;
} while (_domWriteHead != null || _domReadHead != null);
_runAsyncFns();
} while (_domWriteHead != null || _domReadHead != null || _runAsyncHead != null);
_stats.flushEnd();
assert((() {
_stats.flushAssertStart();
Expand Down Expand Up @@ -788,7 +782,7 @@ class RootScope extends Scope {

// QUEUES
void runAsync(fn()) {
if (_state == STATE_FLUSH || _state == STATE_FLUSH_ASSERT) {
if (_state == STATE_FLUSH_ASSERT) {
throw "Scheduling microtasks not allowed in $state state.";
}
var chain = new _FunctionChain(fn);
Expand All @@ -799,6 +793,21 @@ class RootScope extends Scope {
}
}

_runAsyncFns() {
var count = 0;
while (_runAsyncHead != null) {
try {
count++;
_runAsyncHead.fn();
} catch (e, s) {
_exceptionHandler(e, s);
}
_runAsyncHead = _runAsyncHead._next;
}
_runAsyncTail = null;
return count;
}

void domWrite(fn()) {
var chain = new _FunctionChain(fn);
if (_domWriteHead == null) {
Expand Down
27 changes: 24 additions & 3 deletions test/core/scope_spec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1227,6 +1227,20 @@ void main() {
});


it(r'should detect infinite digest through runAsync', (RootScope rootScope) {
rootScope.context['value'] = () { rootScope.runAsync(() {}); return 'a'; };
rootScope.watch('value()', (_, __) {});

expect(() {
rootScope.digest();
}).toThrow('Model did not stabilize in 5 digests. '
'Last 3 iterations:\n'
'async:1\n'
'async:1\n'
'async:1');
});


it(r'should always call the watchr with newVal and oldVal equal on the first run',
inject((RootScope rootScope) {
var log = [];
Expand Down Expand Up @@ -1500,15 +1514,22 @@ void main() {
})
);

it('should not allow microtasks in flush phase',
it('should allow microtasks in flush phase and process them immediatly',
async((Logger log, VmTurnZone zone, RootScope scope) {
scope.watch('g()', (_, __) {});
scope.context['g'] = () {
log('!');
return 0;
};

zone.run(() {
scope.domWrite(() {
return new Future.value('FAIL');
log('domWriteA');
return new Future.value(null).then((_) => scope.domWrite(() => log('domWriteB')));
});
});
expect(log).toEqual(
['[', '(', 'CATCH: Scheduling microtasks not allowed in flush state.', ')', ']']);
['[', '!', '!', 'domWriteA', '(', ')', 'domWriteB', /* assert */'!', ']']);
})
);

Expand Down

1 comment on commit d1e745e

@jbdeboer
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TO BE REVERTED

Please sign in to comment.