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

Unified Diff: pkg/observe/lib/src/path_observer.dart

Issue 27618002: package:observe fix various api issues (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 2 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
« no previous file with comments | « pkg/observe/lib/src/observable_map.dart ('k') | pkg/observe/lib/transform.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/observe/lib/src/path_observer.dart
diff --git a/pkg/observe/lib/src/path_observer.dart b/pkg/observe/lib/src/path_observer.dart
index c6e0be02bc30869968f14ca8d61dbf16d5144461..1b6e1a34dc1a80b7638bf918a0897b763616e81a 100644
--- a/pkg/observe/lib/src/path_observer.dart
+++ b/pkg/observe/lib/src/path_observer.dart
@@ -21,7 +21,7 @@ part of observe;
*
* This class is used to implement [Node.bind] and similar functionality.
*/
-class PathObserver extends ChangeNotifierBase {
+class PathObserver extends ChangeNotifier {
/** The path string. */
final String path;
@@ -119,21 +119,19 @@ class PathObserver extends ChangeNotifierBase {
}
void _updateObservedValues([int start = 0]) {
- bool changed = false;
+ var oldValue, newValue;
for (int i = start; i < _segments.length; i++) {
- final newValue = _getObjectProperty(_values[i], _segments[i]);
- if (identical(_values[i + 1], newValue)) {
+ oldValue = _values[i + 1];
+ newValue = _getObjectProperty(_values[i], _segments[i]);
+ if (identical(oldValue, newValue)) {
_observePath(start, i);
return;
}
_values[i + 1] = newValue;
- changed = true;
}
_observePath(start);
- if (changed) {
- notifyChange(new PropertyChangeRecord(#value));
- }
+ notifyPropertyChange(#value, oldValue, newValue);
}
void _observePath([int start = 0, int end]) {
@@ -160,7 +158,7 @@ class PathObserver extends ChangeNotifierBase {
}
for (var record in records) {
- if (record.changes(_segments[i])) {
+ if (_changeRecordMatches(record, _segments[i])) {
_updateObservedValues(i);
return;
}
@@ -170,6 +168,20 @@ class PathObserver extends ChangeNotifierBase {
}
}
+bool _changeRecordMatches(record, key) {
+ if (record is ListChangeRecord) {
+ return key is int && (record as ListChangeRecord).indexChanged(key);
+ }
+ if (record is PropertyChangeRecord) {
+ return (record as PropertyChangeRecord).name == key;
+ }
+ if (record is MapChangeRecord) {
+ if (key is Symbol) key = MirrorSystem.getName(key);
+ return (record as MapChangeRecord).key == key;
+ }
+ return false;
+}
+
_getObjectProperty(object, property) {
if (object == null) {
return null;
@@ -185,12 +197,12 @@ _getObjectProperty(object, property) {
if (property is Symbol) {
var mirror = reflect(object);
- try {
- return mirror.getField(property).reflectee;
- } catch (e) {}
+ var result = _tryGetField(mirror, property);
+ if (result != null) return result.reflectee;
}
if (object is Map) {
+ if (property is Symbol) property = MirrorSystem.getName(property);
return object[property];
}
@@ -209,13 +221,11 @@ bool _setObjectProperty(object, property, value) {
if (property is Symbol) {
var mirror = reflect(object);
- try {
- mirror.setField(property, value);
- return true;
- } catch (e) {}
+ if (_trySetField(mirror, property, value)) return true;
}
if (object is Map) {
+ if (property is Symbol) property = MirrorSystem.getName(property);
object[property] = value;
return true;
}
@@ -223,6 +233,58 @@ bool _setObjectProperty(object, property, value) {
return false;
}
+InstanceMirror _tryGetField(InstanceMirror mirror, Symbol name) {
+ try {
+ return mirror.getField(name);
+ } on NoSuchMethodError catch (e) {
+ if (_hasMember(mirror, name, (m) =>
+ m is VariableMirror || m is MethodMirror && m.isGetter)) {
+ // The field/getter is there but threw a NoSuchMethod exception.
+ // This is a legitimate error in the code so rethrow.
+ rethrow;
+ }
+ // The field isn't there. PathObserver does not treat this as an error.
+ return null;
+ }
+}
+
+bool _trySetField(InstanceMirror mirror, Symbol name, Object value) {
+ try {
+ mirror.setField(name, value);
+ return true;
+ } on NoSuchMethodError catch (e) {
+ if (_hasMember(mirror, name, (m) => m is VariableMirror) ||
+ _hasMember(mirror, _setterName(name))) {
+ // The field/setter is there but threw a NoSuchMethod exception.
+ // This is a legitimate error in the code so rethrow.
+ rethrow;
+ }
+ // The field isn't there. PathObserver does not treat this as an error.
+ return false;
+ }
+}
+
+// TODO(jmesserly): workaround for:
+// https://code.google.com/p/dart/issues/detail?id=10029
+Symbol _setterName(Symbol getter) =>
+ new Symbol('${MirrorSystem.getName(getter)}=');
+
+bool _hasMember(InstanceMirror mirror, Symbol name, [bool test(member)]) {
+ var type = mirror.type;
+ while (type != null) {
+ final member = type.members[name];
+ if (member != null && (test == null || test(member))) return true;
+
+ try {
+ type = type.superclass;
+ } on UnsupportedError catch (e) {
+ // TODO(jmesserly): dart2js throws this error when the type is not
+ // reflectable.
+ return false;
+ }
+ }
+ return false;
+}
// From: https://github.com/rafaelw/ChangeSummary/blob/master/change_summary.js
« no previous file with comments | « pkg/observe/lib/src/observable_map.dart ('k') | pkg/observe/lib/transform.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698