| Index: lib/src/path_observer.dart
|
| diff --git a/lib/src/path_observer.dart b/lib/src/path_observer.dart
|
| index 9433480f5fa71d27d10e5822fd2eee23a48a2285..5b4ed99df04e1da9cbbb05d9af2d7e8efa272d9e 100644
|
| --- a/lib/src/path_observer.dart
|
| +++ b/lib/src/path_observer.dart
|
| @@ -132,7 +132,6 @@ class PropertyPath {
|
| var pathObj = _pathCache[path];
|
| if (pathObj != null) return pathObj;
|
|
|
| -
|
| final segments = new _PathParser().parse(path);
|
| if (segments == null) return _InvalidPropertyPath._instance;
|
|
|
| @@ -201,7 +200,7 @@ class PropertyPath {
|
| hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
|
| hash = hash ^ (hash >> 6);
|
| }
|
| - hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
|
| + hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
|
| hash = hash ^ (hash >> 11);
|
| return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
|
| }
|
| @@ -245,7 +244,6 @@ class PropertyPath {
|
| // Dart note: it doesn't make sense to have compiledGetValueFromFn in Dart.
|
| }
|
|
|
| -
|
| /// Visible only for testing:
|
| getSegmentsOfPropertyPathForTesting(p) => p._segments;
|
|
|
| @@ -278,7 +276,8 @@ _getObjectProperty(object, property) {
|
| // 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 Indexable || object is Map && !_MAP_PROPERTIES.contains(property)) {
|
| + if (object is Indexable ||
|
| + object is Map && !_MAP_PROPERTIES.contains(property)) {
|
| return object[smoke.symbolToName(property)];
|
| }
|
| try {
|
| @@ -308,7 +307,8 @@ bool _setObjectProperty(object, property, value) {
|
| }
|
| } else if (property is Symbol) {
|
| // Support indexer if available, e.g. Maps or polymer_expressions Scope.
|
| - if (object is Indexable || object is Map && !_MAP_PROPERTIES.contains(property)) {
|
| + if (object is Indexable ||
|
| + object is Map && !_MAP_PROPERTIES.contains(property)) {
|
| object[smoke.symbolToName(property)] = value;
|
| return true;
|
| }
|
| @@ -339,30 +339,27 @@ _isIdent(s) => _identRegExp.hasMatch(s);
|
| // Dart note: refactored to convert to codepoints once and operate on codepoints
|
| // rather than characters.
|
| class _PathParser {
|
| - List keys = [];
|
| + List<Object> keys = [];
|
| int index = -1;
|
| String key;
|
|
|
| - final Map<String, List<String>> _pathStateMachine = {
|
| + final Map<String, Map<String, List<String>>> _pathStateMachine = {
|
| 'beforePath': {
|
| 'ws': ['beforePath'],
|
| 'ident': ['inIdent', 'append'],
|
| '[': ['beforeElement'],
|
| 'eof': ['afterPath']
|
| },
|
| -
|
| 'inPath': {
|
| 'ws': ['inPath'],
|
| '.': ['beforeIdent'],
|
| '[': ['beforeElement'],
|
| 'eof': ['afterPath']
|
| },
|
| -
|
| 'beforeIdent': {
|
| 'ws': ['beforeIdent'],
|
| 'ident': ['inIdent', 'append']
|
| },
|
| -
|
| 'inIdent': {
|
| 'ident': ['inIdent', 'append'],
|
| '0': ['inIdent', 'append'],
|
| @@ -372,7 +369,6 @@ class _PathParser {
|
| '[': ['beforeElement', 'push'],
|
| 'eof': ['afterPath', 'push']
|
| },
|
| -
|
| 'beforeElement': {
|
| 'ws': ['beforeElement'],
|
| '0': ['afterZero', 'append'],
|
| @@ -380,31 +376,26 @@ class _PathParser {
|
| "'": ['inSingleQuote', 'append', ''],
|
| '"': ['inDoubleQuote', 'append', '']
|
| },
|
| -
|
| 'afterZero': {
|
| 'ws': ['afterElement', 'push'],
|
| ']': ['inPath', 'push']
|
| },
|
| -
|
| 'inIndex': {
|
| '0': ['inIndex', 'append'],
|
| 'number': ['inIndex', 'append'],
|
| 'ws': ['afterElement'],
|
| ']': ['inPath', 'push']
|
| },
|
| -
|
| 'inSingleQuote': {
|
| "'": ['afterElement'],
|
| 'eof': ['error'],
|
| 'else': ['inSingleQuote', 'append']
|
| },
|
| -
|
| 'inDoubleQuote': {
|
| '"': ['afterElement'],
|
| 'eof': ['error'],
|
| 'else': ['inDoubleQuote', 'append']
|
| },
|
| -
|
| 'afterElement': {
|
| 'ws': ['afterElement'],
|
| ']': ['inPath', 'push']
|
| @@ -414,7 +405,7 @@ class _PathParser {
|
| /// From getPathCharType: determines the type of a given [code]point.
|
| String _getPathCharType(code) {
|
| if (code == null) return 'eof';
|
| - switch(code) {
|
| + switch (code) {
|
| case 0x5B: // [
|
| case 0x5D: // ]
|
| case 0x2E: // .
|
| @@ -431,10 +422,10 @@ class _PathParser {
|
| case 0x09: // Tab
|
| case 0x0A: // Newline
|
| case 0x0D: // Return
|
| - case 0xA0: // No-break space
|
| - case 0xFEFF: // Byte Order Mark
|
| - case 0x2028: // Line Separator
|
| - case 0x2029: // Paragraph Separator
|
| + case 0xA0: // No-break space
|
| + case 0xFEFF: // Byte Order Mark
|
| + case 0x2028: // Line Separator
|
| + case 0x2029: // Paragraph Separator
|
| return 'ws';
|
| }
|
|
|
| @@ -443,8 +434,7 @@ class _PathParser {
|
| return 'ident';
|
|
|
| // 1-9
|
| - if (0x31 <= code && code <= 0x39)
|
| - return 'number';
|
| + if (0x31 <= code && code <= 0x39) return 'number';
|
|
|
| return 'else';
|
| }
|
| @@ -482,7 +472,7 @@ class _PathParser {
|
| }
|
|
|
| /// Returns the parsed keys, or null if there was a parse error.
|
| - List<String> parse(String path) {
|
| + List<Object> parse(String path) {
|
| var codePoints = stringToCodepoints(path);
|
| var mode = 'beforePath';
|
|
|
| @@ -491,7 +481,8 @@ class _PathParser {
|
| var c = index >= codePoints.length ? null : codePoints[index];
|
|
|
| if (c != null &&
|
| - _char(c) == '\\' && _maybeUnescapeQuote(mode, codePoints)) continue;
|
| + _char(c) == '\\' &&
|
| + _maybeUnescapeQuote(mode, codePoints)) continue;
|
|
|
| var type = _getPathCharType(c);
|
| if (mode == 'error') return null;
|
| @@ -506,7 +497,8 @@ class _PathParser {
|
| if (actionName == 'push' && key != null) push();
|
| if (actionName == 'append') {
|
| var newChar = transition.length > 2 && transition[2] != null
|
| - ? transition[2] : _char(c);
|
| + ? transition[2]
|
| + : _char(c);
|
| append(newChar);
|
| }
|
|
|
| @@ -518,7 +510,6 @@ class _PathParser {
|
|
|
| final Logger _logger = new Logger('observe.PathObserver');
|
|
|
| -
|
| /// This is a simple cache. It's like LRU but we don't update an item on a
|
| /// cache hit, because that would require allocation. Better to let it expire
|
| /// and reallocate the PropertyPath.
|
| @@ -646,9 +637,9 @@ class CompoundObserver extends _Observer implements Bindable {
|
| var value;
|
| if (identical(object, _observerSentinel)) {
|
| var observable = path as Bindable;
|
| - value = _state == _Observer._UNOPENED ?
|
| - observable.open((_) => this.deliver()) :
|
| - observable.value;
|
| + value = _state == _Observer._UNOPENED
|
| + ? observable.open((_) => this.deliver())
|
| + : observable.value;
|
| } else {
|
| value = (path as PropertyPath).getValueFrom(object);
|
| }
|
| @@ -687,7 +678,10 @@ abstract class Indexable<K, V> {
|
| }
|
|
|
| const _observerSentinel = const _ObserverSentinel();
|
| -class _ObserverSentinel { const _ObserverSentinel(); }
|
| +
|
| +class _ObserverSentinel {
|
| + const _ObserverSentinel();
|
| +}
|
|
|
| // Visible for testing
|
| get observerSentinelForTesting => _observerSentinel;
|
| @@ -764,10 +758,18 @@ abstract class _Observer extends Bindable {
|
| void _report(newValue, oldValue, [extraArg]) {
|
| try {
|
| switch (_notifyArgumentCount) {
|
| - case 0: _notifyCallback(); break;
|
| - case 1: _notifyCallback(newValue); break;
|
| - case 2: _notifyCallback(newValue, oldValue); break;
|
| - case 3: _notifyCallback(newValue, oldValue, extraArg); break;
|
| + case 0:
|
| + _notifyCallback();
|
| + break;
|
| + case 1:
|
| + _notifyCallback(newValue);
|
| + break;
|
| + case 2:
|
| + _notifyCallback(newValue, oldValue);
|
| + break;
|
| + case 3:
|
| + _notifyCallback(newValue, oldValue, extraArg);
|
| + break;
|
| }
|
| } catch (e, s) {
|
| // Deliver errors async, so if a single callback fails it doesn't prevent
|
| @@ -903,7 +905,7 @@ class _ObservedSet {
|
| return true;
|
| }
|
|
|
| - void _callback(records) {
|
| + void _callback(List<ChangeRecord> records) {
|
| if (_canIgnoreRecords(records)) return;
|
| for (var observer in _observers.toList(growable: false)) {
|
| if (observer._isOpen) observer._iterateObjects(observe);
|
|
|