Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Unified Diff: third_party/pkg/angular/lib/change_detection/watch_group.dart

Issue 257423008: Update all Angular libs (run update_all.sh). (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/pkg/angular/lib/change_detection/watch_group.dart
diff --git a/third_party/pkg/angular/lib/change_detection/watch_group.dart b/third_party/pkg/angular/lib/change_detection/watch_group.dart
index f1427b9ba9934f4d510ce844610ad07a7890ea1a..b0dbd05f0f160f267c5e4413767aaa7c720c9eff 100644
--- a/third_party/pkg/angular/lib/change_detection/watch_group.dart
+++ b/third_party/pkg/angular/lib/change_detection/watch_group.dart
@@ -1,18 +1,29 @@
library angular.watch_group;
-import 'dart:mirrors';
import 'package:angular/change_detection/change_detection.dart';
part 'linked_list.dart';
part 'ast.dart';
part 'prototype_map.dart';
-typedef ReactionFn(value, previousValue);
-typedef ChangeLog(String expression, current, previous);
+/**
+ * A function that is notified of changes to the model.
+ *
+ * ReactionFn is a function implemented by the developer that executes when a change is detected
+ * in a watched expression.
+ *
+ * * [value]: The current value of the watched expression.
+ * * [previousValue]: The previous value of the watched expression.
+ *
+ * If the expression is watching a collection (a list or a map), then [value] is wrapped in
+ * a [CollectionChangeItem] that lists all the changes.
+ */
+typedef void ReactionFn(value, previousValue);
+typedef void ChangeLog(String expression, current, previous);
/**
* Extend this class if you wish to pretend to be a function, but you don't know
- * number of arguments with which the function will get called.
+ * number of arguments with which the function will get called with.
*/
abstract class FunctionApply {
// dartbug.com/16401
@@ -56,7 +67,7 @@ class WatchGroup implements _EvalWatchList, _WatchGroupList {
int get totalFieldCost {
var cost = _fieldCost;
WatchGroup group = _watchGroupHead;
- while(group != null) {
+ while (group != null) {
cost += group.totalFieldCost;
group = group._nextWatchGroup;
}
@@ -68,7 +79,7 @@ class WatchGroup implements _EvalWatchList, _WatchGroupList {
int get totalCollectionCost {
var cost = _collectionCost;
WatchGroup group = _watchGroupHead;
- while(group != null) {
+ while (group != null) {
cost += group.totalCollectionCost;
group = group._nextWatchGroup;
}
@@ -82,7 +93,7 @@ class WatchGroup implements _EvalWatchList, _WatchGroupList {
int get totalEvalCost {
var cost = _evalCost;
WatchGroup group = _watchGroupHead;
- while(group != null) {
+ while (group != null) {
cost += group.evalCost;
group = group._nextWatchGroup;
}
@@ -92,9 +103,9 @@ class WatchGroup implements _EvalWatchList, _WatchGroupList {
int _nextChildId = 0;
_EvalWatchRecord _evalWatchHead, _evalWatchTail;
/// Pointer for creating tree of [WatchGroup]s.
- WatchGroup _watchGroupHead, _watchGroupTail, _previousWatchGroup,
- _nextWatchGroup;
WatchGroup _parentWatchGroup;
+ WatchGroup _watchGroupHead, _watchGroupTail;
+ WatchGroup _prevWatchGroup, _nextWatchGroup;
WatchGroup._child(_parentWatchGroup, this._changeDetector, this.context,
this._cache, this._rootGroup)
@@ -118,7 +129,7 @@ class WatchGroup implements _EvalWatchList, _WatchGroupList {
get isAttached {
var group = this;
var root = _rootGroup;
- while(group != null) {
+ while (group != null) {
if (group == root){
return true;
}
@@ -143,7 +154,7 @@ class WatchGroup implements _EvalWatchList, _WatchGroupList {
WatchRecord<_Handler> addFieldWatch(AST lhs, String name, String expression) {
var fieldHandler = new _FieldHandler(this, expression);
- // Create a ChangeRecord for the current field and assign the change record
+ // Create a Record for the current field and assign the change record
// to the handler.
var watchRecord = _changeDetector.watch(null, name, fieldHandler);
_fieldCost++;
@@ -184,10 +195,13 @@ class WatchGroup implements _EvalWatchList, _WatchGroupList {
* - [fn] function to evaluate.
* - [argsAST] list of [AST]es which represent arguments passed to function.
* - [expression] normalized expression used for caching.
+ * - [isPure] A pure function is one which holds no internal state. This implies that the
+ * function is idempotent.
*/
_EvalWatchRecord addFunctionWatch(/* dartbug.com/16401 Function */ fn, List<AST> argsAST,
- String expression) =>
- _addEvalWatch(null, fn, null, argsAST, expression);
+ Map<Symbol, AST> namedArgsAST,
+ String expression, bool isPure) =>
+ _addEvalWatch(null, fn, null, argsAST, namedArgsAST, expression, isPure);
/**
* Watch a method [name]ed represented by an [expression].
@@ -198,16 +212,20 @@ class WatchGroup implements _EvalWatchList, _WatchGroupList {
* - [expression] normalized expression used for caching.
*/
_EvalWatchRecord addMethodWatch(AST lhs, String name, List<AST> argsAST,
+ Map<Symbol, AST> namedArgsAST,
String expression) =>
- _addEvalWatch(lhs, null, name, argsAST, expression);
+ _addEvalWatch(lhs, null, name, argsAST, namedArgsAST, expression, false);
_EvalWatchRecord _addEvalWatch(AST lhsAST, /* dartbug.com/16401 Function */ fn, String name,
- List<AST> argsAST, String expression) {
+ List<AST> argsAST,
+ Map<Symbol, AST> namedArgsAST,
+ String expression, bool isPure) {
_InvokeHandler invokeHandler = new _InvokeHandler(this, expression);
- var evalWatchRecord = new _EvalWatchRecord(this, invokeHandler, fn, name,
- argsAST.length);
+ var evalWatchRecord = new _EvalWatchRecord(
+ _rootGroup._fieldGetterFactory, this, invokeHandler, fn, name,
+ argsAST.length, isPure);
invokeHandler.watchRecord = evalWatchRecord;
if (lhsAST != null) {
@@ -218,20 +236,35 @@ class WatchGroup implements _EvalWatchList, _WatchGroupList {
}
// Convert the args from AST to WatchRecords
- var i = 0;
- argsAST.
- map((ast) => _cache.putIfAbsent(ast.expression,
- () => ast.setupWatch(this))).forEach((WatchRecord<_Handler> record) {
- var argHandler = new _ArgHandler(this, evalWatchRecord, i++);
- _ArgHandlerList._add(invokeHandler, argHandler);
- record.handler.addForwardHandler(argHandler);
- argHandler.acceptValue(record.currentValue);
+ Iterable<WatchRecord<_Handler>> records = argsAST.map((ast) =>
+ _cache.putIfAbsent(ast.expression, () => ast.setupWatch(this)));
+ int i = 0;
+ records.forEach((WatchRecord<_Handler> record) {
+ _ArgHandler handler = new _PositionalArgHandler(this, evalWatchRecord, i++);
+ _ArgHandlerList._add(invokeHandler, handler);
+ record.handler.addForwardHandler(handler);
+ handler.acceptValue(record.currentValue);
+ });
+
+ namedArgsAST.forEach((Symbol name, AST ast) {
+ WatchRecord<_Handler> record = _cache.putIfAbsent(ast.expression,
+ () => ast.setupWatch(this));
+ _ArgHandler handler = new _NamedArgHandler(this, evalWatchRecord, name);
+ _ArgHandlerList._add(invokeHandler, handler);
+ record.handler.addForwardHandler(handler);
+ handler.acceptValue(record.currentValue);
});
// Must be done last
_EvalWatchList._add(this, evalWatchRecord);
_evalCost++;
-
+ if (_rootGroup.isInsideInvokeDirty) {
+ // This check means that we are inside invoke reaction function.
+ // Registering a new EvalWatch at this point will not run the
+ // .check() on it which means it will not be processed, but its
+ // reaction function will be run with null. So we process it manually.
+ evalWatchRecord.check();
+ }
return evalWatchRecord;
}
@@ -257,15 +290,15 @@ class WatchGroup implements _EvalWatchList, _WatchGroupList {
this,
_changeDetector.newGroup(),
context == null ? this.context : context,
- context == null ? this._cache: <String, WatchRecord<_Handler>>{},
+ <String, WatchRecord<_Handler>>{},
_rootGroup == null ? this : _rootGroup);
_WatchGroupList._add(this, childGroup);
var marker = childGroup._marker;
- marker._previousEvalWatch = prev;
+ marker._prevEvalWatch = prev;
marker._nextEvalWatch = next;
- if (prev != null) prev._nextEvalWatch = marker;
- if (next != null) next._previousEvalWatch = marker;
+ prev._nextEvalWatch = marker;
+ if (next != null) next._prevEvalWatch = marker;
return childGroup;
}
@@ -276,21 +309,23 @@ class WatchGroup implements _EvalWatchList, _WatchGroupList {
void remove() {
// TODO:(misko) This code is not right.
// 1) It fails to release [ChangeDetector] [WatchRecord]s.
- // 2) it needs to cleanup caches if the cache is being shared.
_WatchGroupList._remove(_parentWatchGroup, this);
+ _nextWatchGroup = _prevWatchGroup = null;
_changeDetector.remove();
_rootGroup._removeCount++;
_parentWatchGroup = null;
// Unlink the _watchRecord
_EvalWatchRecord firstEvalWatch = _evalWatchHead;
- _EvalWatchRecord lastEvalWatch =
- (_watchGroupTail == null ? this : _watchGroupTail)._evalWatchTail;
- _EvalWatchRecord previous = firstEvalWatch._previousEvalWatch;
+ _EvalWatchRecord lastEvalWatch = _childWatchGroupTail._evalWatchTail;
+ _EvalWatchRecord previous = firstEvalWatch._prevEvalWatch;
_EvalWatchRecord next = lastEvalWatch._nextEvalWatch;
if (previous != null) previous._nextEvalWatch = next;
- if (next != null) next._previousEvalWatch = previous;
+ if (next != null) next._prevEvalWatch = previous;
+ _evalWatchHead._prevEvalWatch = null;
+ _evalWatchTail._nextEvalWatch = null;
+ _evalWatchHead = _evalWatchTail = null;
}
toString() {
@@ -301,7 +336,7 @@ class WatchGroup implements _EvalWatchList, _WatchGroupList {
var prev = null;
while (watch != null) {
allWatches.add(watch.toString());
- assert(watch._previousEvalWatch == prev);
+ assert(watch._prevEvalWatch == prev);
prev = watch;
watch = watch._nextEvalWatch;
}
@@ -319,7 +354,7 @@ class WatchGroup implements _EvalWatchList, _WatchGroupList {
lines.add('WatchGroup[$id](watches: ${watches.join(', ')})');
var childGroup = _watchGroupHead;
while (childGroup != null) {
- lines.add(' ' + childGroup.toString().split('\n').join('\n '));
+ lines.add(' ' + childGroup.toString().replace('\n', '\n '));
childGroup = childGroup._nextWatchGroup;
}
return lines.join('\n');
@@ -330,6 +365,7 @@ class WatchGroup implements _EvalWatchList, _WatchGroupList {
* [RootWatchGroup]
*/
class RootWatchGroup extends WatchGroup {
+ final FieldGetterFactory _fieldGetterFactory;
Watch _dirtyWatchHead, _dirtyWatchTail;
/**
@@ -342,8 +378,10 @@ class RootWatchGroup extends WatchGroup {
int _removeCount = 0;
- RootWatchGroup(ChangeDetector changeDetector, Object context):
- super._root(changeDetector, context);
+ RootWatchGroup(this._fieldGetterFactory,
+ ChangeDetector changeDetector,
+ Object context)
+ : super._root(changeDetector, context);
RootWatchGroup get _rootGroup => this;
@@ -359,22 +397,22 @@ class RootWatchGroup extends WatchGroup {
* previous steps are completed).
*/
int detectChanges({ EvalExceptionHandler exceptionHandler,
- ChangeLog changeLog,
+ ChangeLog changeLog,
AvgStopwatch fieldStopwatch,
AvgStopwatch evalStopwatch,
AvgStopwatch processStopwatch}) {
- // Process the ChangeRecords from the change detector
- ChangeRecord<_Handler> changeRecord =
+ // Process the Records from the change detector
+ Iterator<Record<_Handler>> changedRecordIterator =
(_changeDetector as ChangeDetector<_Handler>).collectChanges(
- exceptionHandler:exceptionHandler,
+ exceptionHandler:exceptionHandler,
stopwatch: fieldStopwatch);
if (processStopwatch != null) processStopwatch.start();
- while (changeRecord != null) {
- if (changeLog != null) changeLog(changeRecord.handler.expression,
- changeRecord.currentValue,
- changeRecord.previousValue);
- changeRecord.handler.onChange(changeRecord);
- changeRecord = changeRecord.nextChange;
+ while (changedRecordIterator.moveNext()) {
+ var record = changedRecordIterator.current;
+ if (changeLog != null) changeLog(record.handler.expression,
+ record.currentValue,
+ record.previousValue);
+ record.handler.onChange(record);
}
if (processStopwatch != null) processStopwatch.stop();
@@ -385,8 +423,7 @@ class RootWatchGroup extends WatchGroup {
while (evalRecord != null) {
try {
if (evalStopwatch != null) evalCount++;
- var change = evalRecord.check();
- if (change != null && changeLog != null) {
+ if (evalRecord.check() && changeLog != null) {
changeLog(evalRecord.handler.expression,
evalRecord.currentValue,
evalRecord.previousValue);
@@ -402,26 +439,35 @@ class RootWatchGroup extends WatchGroup {
// We need to call reaction functions asynchronously. This processes the
// asynchronous reaction function queue.
int count = 0;
- if (processStopwatch != null) processStopwatch.stop();
+ if (processStopwatch != null) processStopwatch.start();
Watch dirtyWatch = _dirtyWatchHead;
+ _dirtyWatchHead = null;
RootWatchGroup root = _rootGroup;
- root._removeCount = 0;
- while(dirtyWatch != null) {
- count++;
- try {
- if (root._removeCount == 0 || dirtyWatch._watchGroup.isAttached) {
- dirtyWatch.invoke();
+ try {
+ while (dirtyWatch != null) {
+ count++;
+ try {
+ if (root._removeCount == 0 || dirtyWatch._watchGroup.isAttached) {
+ dirtyWatch.invoke();
+ }
+ } catch (e, s) {
+ if (exceptionHandler == null) rethrow; else exceptionHandler(e, s);
}
- } catch (e, s) {
- if (exceptionHandler == null) rethrow; else exceptionHandler(e, s);
+ var nextDirtyWatch = dirtyWatch._nextDirtyWatch;
+ dirtyWatch._nextDirtyWatch = null;
+ dirtyWatch = nextDirtyWatch;
}
- dirtyWatch = dirtyWatch._nextDirtyWatch;
+ } finally {
+ _dirtyWatchTail = null;
+ root._removeCount = 0;
}
- _dirtyWatchHead = _dirtyWatchTail = null;
if (processStopwatch != null) processStopwatch..stop()..increment(count);
return count;
}
+ bool get isInsideInvokeDirty =>
+ _dirtyWatchHead == null && _dirtyWatchTail != null;
+
/**
* Add Watch into the asynchronous queue for later processing.
*/
@@ -490,6 +536,7 @@ class Watch {
* changes detected at one handler are propagated to the next handler.
*/
abstract class _Handler implements _LinkedList, _LinkedListItem, _WatchList {
+ // Used for forwarding changes to delegates
_Handler _head, _tail;
_Handler _next, _previous;
Watch _watchHead, _watchTail;
@@ -517,7 +564,8 @@ abstract class _Handler implements _LinkedList, _LinkedListItem, _WatchList {
forwardToHandler.forwardingHandler = this;
}
- void release() {
+ /// Return true if release has happened
+ bool release() {
if (_WatchList._isEmpty(this) && _LinkedList._isEmpty(this)) {
_releaseWatch();
// Remove ourselves from cache, or else new registrations will go to us,
@@ -532,6 +580,9 @@ abstract class _Handler implements _LinkedList, _LinkedListItem, _WatchList {
// We can remove ourselves
assert((_next = _previous = this) == this); // mark ourselves as detached
+ return true;
+ } else {
+ return false;
}
}
@@ -541,12 +592,12 @@ abstract class _Handler implements _LinkedList, _LinkedListItem, _WatchList {
}
acceptValue(object) => null;
- void onChange(ChangeRecord<_Handler> record) {
+ void onChange(Record<_Handler> record) {
assert(_next != this); // verify we are not detached
// If we have reaction functions than queue them up for asynchronous
// processing.
Watch watch = _watchHead;
- while(watch != null) {
+ while (watch != null) {
watchGrp._rootGroup._addDirtyWatch(watch);
watch = watch._nextWatch;
}
@@ -560,7 +611,7 @@ abstract class _Handler implements _LinkedList, _LinkedListItem, _WatchList {
}
class _ConstantHandler extends _Handler {
- _ConstantHandler(WatchGroup watchGroup, String expression, dynamic constantValue)
+ _ConstantHandler(WatchGroup watchGroup, String expression, constantValue)
: super(watchGroup, expression)
{
watchRecord = new _EvalWatchRecord.constant(this, constantValue);
@@ -577,8 +628,7 @@ class _FieldHandler extends _Handler {
*/
void acceptValue(object) {
watchRecord.object = object;
- var changeRecord = watchRecord.check();
- if (changeRecord != null) onChange(changeRecord);
+ if (watchRecord.check()) onChange(watchRecord);
}
}
@@ -590,8 +640,7 @@ class _CollectionHandler extends _Handler {
*/
void acceptValue(object) {
watchRecord.object = object;
- var changeRecord = watchRecord.check();
- if (changeRecord != null) onChange(changeRecord);
+ if (watchRecord.check()) onChange(watchRecord);
}
void _releaseWatch() {
@@ -600,18 +649,22 @@ class _CollectionHandler extends _Handler {
}
}
-class _ArgHandler extends _Handler {
+abstract class _ArgHandler extends _Handler {
_ArgHandler _previousArgHandler, _nextArgHandler;
// TODO(misko): Why do we override parent?
final _EvalWatchRecord watchRecord;
- final int index;
+ _ArgHandler(WatchGroup watchGrp, String expression, this.watchRecord)
+ : super(watchGrp, expression);
_releaseWatch() => null;
+}
- _ArgHandler(WatchGroup watchGrp, this.watchRecord, int index)
- : index = index,
- super(watchGrp, 'arg[$index]');
+class _PositionalArgHandler extends _ArgHandler {
+ final int index;
+ _PositionalArgHandler(WatchGroup watchGrp, _EvalWatchRecord record, int index)
+ : this.index = index,
+ super(watchGrp, 'arg[$index]', record);
void acceptValue(object) {
watchRecord.dirtyArgs = true;
@@ -619,6 +672,19 @@ class _ArgHandler extends _Handler {
}
}
+class _NamedArgHandler extends _ArgHandler {
+ final Symbol name;
+
+ _NamedArgHandler(WatchGroup watchGrp, _EvalWatchRecord record, Symbol name)
+ : this.name = name,
+ super(watchGrp, 'namedArg[$name]', record);
+
+ void acceptValue(object) {
+ watchRecord.dirtyArgs = true;
+ watchRecord.namedArgs[name] = object;
+ }
+}
+
class _InvokeHandler extends _Handler implements _ArgHandlerList {
_ArgHandler _argHandlerHead, _argHandlerTail;
@@ -629,55 +695,58 @@ class _InvokeHandler extends _Handler implements _ArgHandlerList {
watchRecord.object = object;
}
- void onChange(ChangeRecord<_Handler> record) {
- super.onChange(record);
- }
-
void _releaseWatch() {
(watchRecord as _EvalWatchRecord).remove();
}
- void release() {
- super.release();
- _ArgHandler current = _argHandlerHead;
- while(current != null) {
- current.release();
- current = current._nextArgHandler;
+ bool release() {
+ if (super.release()) {
+ _ArgHandler current = _argHandlerHead;
+ while (current != null) {
+ current.release();
+ current = current._nextArgHandler;
+ }
+ return true;
+ } else {
+ return false;
}
}
}
-class _EvalWatchRecord implements WatchRecord<_Handler>, ChangeRecord<_Handler> {
- static const int _MODE_DELETED_ = -1;
- static const int _MODE_MARKER_ = 0;
- static const int _MODE_FUNCTION_ = 1;
- static const int _MODE_FUNCTION_APPLY_ = 2;
- static const int _MODE_NULL_ = 3;
- static const int _MODE_FIELD_CLOSURE_ = 4;
- static const int _MODE_MAP_CLOSURE_ = 5;
- static const int _MODE_METHOD_ = 6;
+class _EvalWatchRecord implements WatchRecord<_Handler> {
+ static const int _MODE_INVALID_ = -2;
+ static const int _MODE_DELETED_ = -1;
+ static const int _MODE_MARKER_ = 0;
+ static const int _MODE_PURE_FUNCTION_ = 1;
+ static const int _MODE_FUNCTION_ = 2;
+ static const int _MODE_PURE_FUNCTION_APPLY_ = 3;
+ static const int _MODE_NULL_ = 4;
+ static const int _MODE_FIELD_CLOSURE_ = 5;
+ static const int _MODE_MAP_CLOSURE_ = 6;
+ static const int _MODE_METHOD_ = 7;
+ static const int _MODE_METHOD_INVOKE_ = 8;
WatchGroup watchGrp;
final _Handler handler;
final List args;
- final Symbol symbol;
+ final Map<Symbol, dynamic> namedArgs = new Map<Symbol, dynamic>();
final String name;
int mode;
/* dartbug.com/16401 Function*/ var fn;
- InstanceMirror _instanceMirror;
+ FieldGetterFactory _fieldGetterFactory;
bool dirtyArgs = true;
dynamic currentValue, previousValue, _object;
- _EvalWatchRecord _previousEvalWatch, _nextEvalWatch;
+ _EvalWatchRecord _prevEvalWatch, _nextEvalWatch;
- _EvalWatchRecord(this.watchGrp, this.handler, this.fn, name, int arity)
- : args = new List(arity),
- name = name,
- symbol = name == null ? null : new Symbol(name) {
+ _EvalWatchRecord(this._fieldGetterFactory, this.watchGrp, this.handler,
+ this.fn, this.name, int arity, bool pure)
+ : args = new List(arity)
+ {
if (fn is FunctionApply) {
- mode = _MODE_FUNCTION_APPLY_;
+ mode = pure ? _MODE_PURE_FUNCTION_APPLY_: _MODE_INVALID_;
} else if (fn is Function) {
- mode = _MODE_FUNCTION_;
+ mode = pure ? _MODE_PURE_FUNCTION_ : _MODE_FUNCTION_;
} else {
mode = _MODE_NULL_;
}
@@ -685,21 +754,21 @@ class _EvalWatchRecord implements WatchRecord<_Handler>, ChangeRecord<_Handler>
_EvalWatchRecord.marker()
: mode = _MODE_MARKER_,
+ _fieldGetterFactory = null,
watchGrp = null,
handler = null,
args = null,
fn = null,
- symbol = null,
name = null;
_EvalWatchRecord.constant(_Handler handler, dynamic constantValue)
: mode = _MODE_MARKER_,
+ _fieldGetterFactory = null,
handler = handler,
currentValue = constantValue,
watchGrp = null,
args = null,
fn = null,
- symbol = null,
name = null;
get field => '()';
@@ -710,8 +779,8 @@ class _EvalWatchRecord implements WatchRecord<_Handler>, ChangeRecord<_Handler>
assert(mode != _MODE_DELETED_);
assert(mode != _MODE_MARKER_);
assert(mode != _MODE_FUNCTION_);
- assert(mode != _MODE_FUNCTION_APPLY_);
- assert(symbol != null);
+ assert(mode != _MODE_PURE_FUNCTION_);
+ assert(mode != _MODE_PURE_FUNCTION_APPLY_);
_object = value;
if (value == null) {
@@ -720,40 +789,50 @@ class _EvalWatchRecord implements WatchRecord<_Handler>, ChangeRecord<_Handler>
if (value is Map) {
mode = _MODE_MAP_CLOSURE_;
} else {
- _instanceMirror = reflect(value);
- mode = _hasMethod(_instanceMirror.type, symbol)
- ? _MODE_METHOD_
- : _MODE_FIELD_CLOSURE_;
+ if (_fieldGetterFactory.isMethod(value, name)) {
+ mode = _fieldGetterFactory.isMethodInvoke ? _MODE_METHOD_INVOKE_ : _MODE_METHOD_;
+ fn = _fieldGetterFactory.method(value, name);
+ } else {
+ mode = _MODE_FIELD_CLOSURE_;
+ fn = _fieldGetterFactory.getter(value, name);
+ }
}
}
}
- ChangeRecord<_Handler> check() {
+ bool check() {
var value;
switch (mode) {
case _MODE_MARKER_:
case _MODE_NULL_:
- return null;
+ return false;
+ case _MODE_PURE_FUNCTION_:
+ if (!dirtyArgs) return false;
+ value = Function.apply(fn, args, namedArgs);
+ dirtyArgs = false;
+ break;
case _MODE_FUNCTION_:
- if (!dirtyArgs) return null;
- value = Function.apply(fn, args);
+ value = Function.apply(fn, args, namedArgs);
dirtyArgs = false;
break;
- case _MODE_FUNCTION_APPLY_:
- if (!dirtyArgs) return null;
+ case _MODE_PURE_FUNCTION_APPLY_:
+ if (!dirtyArgs) return false;
value = (fn as FunctionApply).apply(args);
dirtyArgs = false;
break;
case _MODE_FIELD_CLOSURE_:
- var closure = _instanceMirror.getField(symbol).reflectee;
- value = closure == null ? null : Function.apply(closure, args);
+ var closure = fn(_object);
+ value = closure == null ? null : Function.apply(closure, args, namedArgs);
break;
case _MODE_MAP_CLOSURE_:
var closure = object[name];
- value = closure == null ? null : Function.apply(closure, args);
+ value = closure == null ? null : Function.apply(closure, args, namedArgs);
break;
case _MODE_METHOD_:
- value = _instanceMirror.invoke(symbol, args).reflectee;
+ value = Function.apply(fn, args, namedArgs);
+ break;
+ case _MODE_METHOD_INVOKE_:
+ value = fn(args, namedArgs);
break;
default:
assert(false);
@@ -768,10 +847,10 @@ class _EvalWatchRecord implements WatchRecord<_Handler>, ChangeRecord<_Handler>
previousValue = current;
currentValue = value;
handler.onChange(this);
- return this;
+ return true;
}
}
- return null;
+ return false;
}
get nextChange => null;
@@ -787,45 +866,4 @@ class _EvalWatchRecord implements WatchRecord<_Handler>, ChangeRecord<_Handler>
if (mode == _MODE_MARKER_) return 'MARKER[$currentValue]';
return '${watchGrp.id}:${handler.expression}';
}
-
- static final Function _hasMethod = (() {
- var objectClassMirror = reflectClass(Object);
- Set<Symbol> objectClassInstanceMethods =
- new Set<Symbol>.from([#toString, #noSuchMethod]);
- try {
- // Use ClassMirror.instanceMembers if available. It contains local
- // as well as inherited members.
- objectClassMirror.instanceMembers;
- // For SDK 1.2 we have to use a somewhat complicated helper for this
- // to work around bugs in the dart2js implementation.
- return (type, symbol) {
- // Always allow instance methods found in the Object class. This makes
- // it easier to work around a few bugs in the dart2js implementation.
- if (objectClassInstanceMethods.contains(symbol)) return true;
- // Work around http://dartbug.com/16309 which causes access to the
- // instance members of certain builtin types to throw exceptions
- // while traversing the superclass chain.
- var mirror;
- try {
- mirror = type.instanceMembers[symbol];
- } on UnsupportedError catch (e) {
- mirror = type.declarations[symbol];
- }
- // Work around http://dartbug.com/15760 which causes noSuchMethod
- // forwarding stubs to be treated as members of all classes. We have
- // already checked for the real instance methods in Object, so if the
- // owner of this method is Object we simply filter it out.
- if (mirror is !MethodMirror) return false;
- return mirror.owner != objectClassMirror;
- };
- } on NoSuchMethodError catch (e) {
- // For SDK 1.0 we fall back to just using the local members.
- return (type, symbol) => type.members[symbol] is MethodMirror;
- } on UnimplementedError catch (e) {
- // For SDK 1.1 we fall back to just using the local declarations.
- return (type, symbol) => type.declarations[symbol] is MethodMirror;
- }
- return null;
- })();
-
}

Powered by Google App Engine
This is Rietveld 408576698