diff --git a/lib/change_detection/change_detection.dart b/lib/change_detection/change_detection.dart index c3394708a..855d7b86f 100644 --- a/lib/change_detection/change_detection.dart +++ b/lib/change_detection/change_detection.dart @@ -55,7 +55,8 @@ abstract class ChangeDetector extends ChangeDetectorGroup { * same order as they were registered. */ Iterator> collectChanges({ EvalExceptionHandler exceptionHandler, - AvgStopwatch stopwatch }); + AvgStopwatch stopwatch, + bool reMemoizeForPureFunc }); } abstract class Record { diff --git a/lib/change_detection/dirty_checking_change_detector.dart b/lib/change_detection/dirty_checking_change_detector.dart index f276ff7e4..bdbc6b677 100644 --- a/lib/change_detection/dirty_checking_change_detector.dart +++ b/lib/change_detection/dirty_checking_change_detector.dart @@ -282,13 +282,14 @@ class DirtyCheckingChangeDetector extends DirtyCheckingChangeDetectorGroup } Iterator> collectChanges({EvalExceptionHandler exceptionHandler, - AvgStopwatch stopwatch}) { + AvgStopwatch stopwatch, bool reMemoizeForPureFunc}) { if (stopwatch != null) stopwatch.start(); DirtyCheckingRecord changeTail = _fakeHead; DirtyCheckingRecord current = _recordHead; // current index int count = 0; while (current != null) { + if (reMemoizeForPureFunc == null || reMemoizeForPureFunc) current.dirtyArgs = true; try { if (current.check()) changeTail = changeTail._nextChange = current; count++; @@ -373,6 +374,7 @@ class DirtyCheckingRecord implements Record, WatchRecord { Record _nextChange; var _object; InstanceMirror _instanceMirror; + bool dirtyArgs = true; DirtyCheckingRecord(this._group, object, fieldName, this._getter, this.handler) : field = fieldName, @@ -443,7 +445,9 @@ class DirtyCheckingRecord implements Record, WatchRecord { case _MODE_MARKER_: return false; case _MODE_REFLECT_: + if (!dirtyArgs) return false; current = _instanceMirror.getField(_symbol).reflectee; + if (object is List) dirtyArgs = false; break; case _MODE_GETTER_: current = _getter(object); diff --git a/lib/change_detection/watch_group.dart b/lib/change_detection/watch_group.dart index a409a0643..1b14be4c4 100644 --- a/lib/change_detection/watch_group.dart +++ b/lib/change_detection/watch_group.dart @@ -370,12 +370,13 @@ class RootWatchGroup extends WatchGroup { ChangeLog changeLog, AvgStopwatch fieldStopwatch, AvgStopwatch evalStopwatch, - AvgStopwatch processStopwatch}) { + AvgStopwatch processStopwatch, bool reMemoizeForPureFunc : true}) { // Process the Records from the change detector Iterator> changedRecordIterator = (_changeDetector as ChangeDetector<_Handler>).collectChanges( exceptionHandler:exceptionHandler, - stopwatch: fieldStopwatch); + stopwatch: fieldStopwatch, + reMemoizeForPureFunc: reMemoizeForPureFunc); if (processStopwatch != null) processStopwatch.start(); while (changedRecordIterator.moveNext()) { var record = changedRecordIterator.current; diff --git a/lib/core/scope.dart b/lib/core/scope.dart index 4f34a794d..3f0cb84a3 100644 --- a/lib/core/scope.dart +++ b/lib/core/scope.dart @@ -467,7 +467,8 @@ class RootScope extends Scope { changeLog: changeLog, fieldStopwatch: _scopeStats.digestFieldStopwatch, evalStopwatch: _scopeStats.digestEvalStopwatch, - processStopwatch: _scopeStats.digestProcessStopwatch); + processStopwatch: _scopeStats.digestProcessStopwatch, + reMemoizeForPureFunc: count == null); if (digestTTL <= LOG_COUNT) { if (changeLog == null) { diff --git a/test/core/scope_spec.dart b/test/core/scope_spec.dart index cc700f9d9..741886623 100644 --- a/test/core/scope_spec.dart +++ b/test/core/scope_spec.dart @@ -161,6 +161,19 @@ void main() { rootScope.digest(); expect(logger).toEqual([true]); }); + + it('should watch list property as pure', (Logger logger, Map context, RootScope rootScope) { + var list = [true, 2, 'abc']; + final logVal = (value, _) => logger(value); + context['list'] = list; + rootScope.watch('list.reversed', logVal); + rootScope.digest(); + expect(logger).toEqual([['abc', 2, true]]); + logger.clear(); + context['list'][2] = 'def'; + rootScope.digest(); + expect(logger).toEqual([['def', 2, true]]); + }); it('should support filters', (Logger logger, Map context, RootScope rootScope, AstParser parser,