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

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

Issue 211763002: Change path-observer to lookup properties aggressively and report errors (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 9 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 | « no previous file | pkg/observe/test/path_observer_test.dart » ('j') | pkg/observe/test/path_observer_test.dart » ('J')
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 0d631a0c192829fb51726b968157ebbf13c3b554..b7d83172d1606a0b7924772af55fe04d272ab4a9 100644
--- a/pkg/observe/lib/src/path_observer.dart
+++ b/pkg/observe/lib/src/path_observer.dart
@@ -83,7 +83,10 @@ class PathObserver extends _Observer implements Bindable {
/// A dot-delimieted property path such as "foo.bar" or "foo.10.bar".
Jennifer Messerly 2014/03/25 22:32:44 this was an issue before but: do you mind adding a
Siggi Cherem (dart-lang) 2014/03/26 00:32:07 Done.
/// The path specifies how to get a particular value from an object graph, where
-/// the graph can include arrays.
+/// the graph can include arrays and maps. Each segment of the path describes
+/// how to take a single step in the object graph. Properties like 'foo' or
+/// 'bar' are read as properties on objects, or as keys if the object is a Map
+/// or an [StringIndexer], while integer values are read as indexes in an array.
Jennifer Messerly 2014/03/25 22:32:44 should be "a [StringIndexer]" also, this was an i
Siggi Cherem (dart-lang) 2014/03/26 00:32:07 Done.
// TODO(jmesserly): consider specialized subclasses for:
// * empty path
// * "value"
@@ -180,7 +183,7 @@ class PropertyPath {
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
}
- /// Returns the current of the path from the provided [obj]ect.
+ /// Returns the current value of the path from the provided [obj]ect.
getValueFrom(Object obj) {
if (!isValid) return null;
for (var segment in _segments) {
@@ -233,6 +236,13 @@ bool _changeRecordMatches(record, key) {
return false;
}
+/// Properties in [Map] that need to be read as properties and not as keys in
+/// the map. We exclude methods ('containsValue', 'containsKey', 'putIfAbsent',
+/// 'addAll', 'remove', 'clear', 'forEach') because there is no use in reading
+/// them as part of path-observer segments.
+const _MAP_PROPERTIES =
+ const ['keys', 'values', 'length', 'isEmpty', 'isNotEmpty'];
+
_getObjectProperty(object, property) {
if (object == null) return null;
@@ -241,21 +251,25 @@ _getObjectProperty(object, property) {
return object[property];
}
} else if (property is Symbol) {
- final type = object.runtimeType;
+ var name = smoke.symbolToName(property);
Jennifer Messerly 2014/03/25 22:32:44 move this inside the if, below? and make _MAP_PROP
Siggi Cherem (dart-lang) 2014/03/26 00:32:07 Done.
+ // Support indexer if available, e.g. Maps or polymer_expressions Scope.
+ // This is the default syntax used by polymer/nodebind and
+ // polymer/observe-js PathObserver.
+ // TODO(sigmund): should we also support using checking dynamically for
+ // whether the type practically implements the indexer API
+ // (smoke.hasInstanceMethod(type, const Symbol('[]')))?
+ if (object is StringIndexer ||
+ object is Map && !_MAP_PROPERTIES.contains(name)) {
+ return object[name];
+ }
try {
- if (smoke.hasGetter(type, property) || smoke.hasNoSuchMethod(type)) {
- return smoke.read(object, property);
- }
- // Support indexer if available, e.g. Maps or polymer_expressions Scope.
- // This is the default syntax used by polymer/nodebind and
- // polymer/observe-js PathObserver.
- if (smoke.hasInstanceMethod(type, const Symbol('[]'))) {
- return object[smoke.symbolToName(property)];
- }
- } on NoSuchMethodError catch (e) {
+ return smoke.read(object, property);
+ } on NoSuchMethodError catch (e, s) {
// Rethrow, unless the type implements noSuchMethod, in which case we
// interpret the exception as a signal that the method was not found.
- if (!smoke.hasNoSuchMethod(type)) rethrow;
+ if (!smoke.hasNoSuchMethod(object.runtimeType)) {
+ new Completer().completeError(e, s);
Jennifer Messerly 2014/03/25 22:32:44 hmmm. Upon second look I'm not sure this is the ri
Siggi Cherem (dart-lang) 2014/03/26 00:32:07 No worries, changed it back to sync. Thanks for fi
+ }
}
}
@@ -274,19 +288,20 @@ bool _setObjectProperty(object, property, value) {
return true;
}
} else if (property is Symbol) {
- final type = object.runtimeType;
+ // Support indexer if available, e.g. Maps or polymer_expressions Scope.
+ var name = smoke.symbolToName(property);
+ if (object is StringIndexer ||
+ object is Map && !_MAP_PROPERTIES.contains(name)) {
+ object[name] = value;
+ return true;
+ }
try {
- if (smoke.hasSetter(type, property) || smoke.hasNoSuchMethod(type)) {
- smoke.write(object, property, value);
- return true;
- }
- // Support indexer if available, e.g. Maps or polymer_expressions Scope.
- if (smoke.hasInstanceMethod(type, const Symbol('[]='))) {
- object[smoke.symbolToName(property)] = value;
- return true;
+ smoke.write(object, property, value);
+ return true;
+ } on NoSuchMethodError catch (e, s) {
+ if (!smoke.hasNoSuchMethod(object.runtimeType)) {
+ new Completer().completeError(e, s);
}
- } on NoSuchMethodError catch (e) {
- if (!smoke.hasNoSuchMethod(type)) rethrow;
}
}
@@ -470,6 +485,13 @@ class CompoundObserver extends _Observer implements Bindable {
}
}
+/// An object accepted by [PropertyPath] where properties are read and written
+/// as indexing operations, just like a [Map].
+abstract class StringIndexer {
Siggi Cherem (dart-lang) 2014/03/25 21:44:25 I was not sure about the name. Other ideas/suggest
Jennifer Messerly 2014/03/25 22:32:44 Indexable<K, V>? then do the is check for Indexabl
Siggi Cherem (dart-lang) 2014/03/26 00:32:07 Done.
+ operator [](String name);
+ operator []=(index, value);
+}
+
const _observerSentinel = const _ObserverSentinel();
class _ObserverSentinel { const _ObserverSentinel(); }
« no previous file with comments | « no previous file | pkg/observe/test/path_observer_test.dart » ('j') | pkg/observe/test/path_observer_test.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698