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

Side by Side Diff: pkg/polymer_expressions/lib/polymer_expressions.dart

Issue 207433002: Changes in polymer-expressions to prepare for codegen in polymer: (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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** 5 /**
6 * A binding delegate used with Polymer elements that 6 * A binding delegate used with Polymer elements that
7 * allows for complex binding expressions, including 7 * allows for complex binding expressions, including
8 * property access, function invocation, 8 * property access, function invocation,
9 * list/map indexing, and two-way filtering. 9 * list/map indexing, and two-way filtering.
10 * 10 *
(...skipping 12 matching lines...) Expand all
23 * [Polymer expressions](http://pub.dartlang.org/packages/polymer_expressions) 23 * [Polymer expressions](http://pub.dartlang.org/packages/polymer_expressions)
24 * pub repository contains detailed documentation about using polymer 24 * pub repository contains detailed documentation about using polymer
25 * expressions. 25 * expressions.
26 */ 26 */
27 27
28 library polymer_expressions; 28 library polymer_expressions;
29 29
30 import 'dart:async'; 30 import 'dart:async';
31 import 'dart:html'; 31 import 'dart:html';
32 32
33 import 'package:logging/logging.dart';
34 import 'package:observe/observe.dart'; 33 import 'package:observe/observe.dart';
35 import 'package:template_binding/template_binding.dart'; 34 import 'package:template_binding/template_binding.dart';
36 35
37 import 'eval.dart'; 36 import 'eval.dart';
38 import 'expression.dart'; 37 import 'expression.dart';
39 import 'parser.dart'; 38 import 'parser.dart';
40 import 'src/globals.dart'; 39 import 'src/globals.dart';
41 40
42 final Logger _logger = new Logger('polymer_expressions');
43
44 // TODO(justin): Investigate XSS protection 41 // TODO(justin): Investigate XSS protection
45 Object _classAttributeConverter(v) => 42 Object _classAttributeConverter(v) =>
46 (v is Map) ? v.keys.where((k) => v[k] == true).join(' ') : 43 (v is Map) ? v.keys.where((k) => v[k] == true).join(' ') :
47 (v is Iterable) ? v.join(' ') : 44 (v is Iterable) ? v.join(' ') :
48 v; 45 v;
49 46
50 Object _styleAttributeConverter(v) => 47 Object _styleAttributeConverter(v) =>
51 (v is Map) ? v.keys.map((k) => '$k: ${v[k]}').join(';') : 48 (v is Map) ? v.keys.map((k) => '$k: ${v[k]}').join(';') :
52 (v is Iterable) ? v.join(';') : 49 (v is Iterable) ? v.join(';') :
53 v; 50 v;
54 51
55 class PolymerExpressions extends BindingDelegate { 52 class PolymerExpressions extends BindingDelegate {
56 /** The default [globals] to use for Polymer expressions. */ 53 /** The default [globals] to use for Polymer expressions. */
57 static const Map DEFAULT_GLOBALS = const { 'enumerate': enumerate }; 54 static const Map DEFAULT_GLOBALS = const { 'enumerate': enumerate };
58 55
59 final Map<String, Object> globals; 56 final Map<String, Object> globals;
60 57
61 /** 58 /**
62 * Creates a new binding delegate for Polymer expressions, with the provided 59 * Creates a new binding delegate for Polymer expressions, with the provided
63 * variables used as [globals]. If no globals are supplied, a copy of the 60 * variables used as [globals]. If no globals are supplied, a copy of the
64 * [DEFAULT_GLOBALS] will be used. 61 * [DEFAULT_GLOBALS] will be used.
65 */ 62 */
66 PolymerExpressions({Map<String, Object> globals}) 63 PolymerExpressions({Map<String, Object> globals})
67 : globals = (globals == null) ? 64 : globals = globals == null ? DEFAULT_GLOBALS : globals;
Siggi Cherem (dart-lang) 2014/03/21 01:43:46 I don't copy it here anymore because we now use th
Jennifer Messerly 2014/03/21 20:08:54 Hmmm, the idea here was that users can dynamically
Siggi Cherem (dart-lang) 2014/03/21 21:09:47 Done. Made _PolymerExpressionsWithEventDelegate pu
68 new Map<String, Object>.from(DEFAULT_GLOBALS) : globals;
69 65
70 prepareBinding(String path, name, node) { 66 prepareBinding(String path, name, node) {
71 if (path == null) return null; 67 if (path == null) return null;
72 var expr = new Parser(path).parse(); 68 var expr = new Parser(path).parse();
73 69
74 // For template bind/repeat to an empty path, just pass through the model. 70 // For template bind/repeat to an empty path, just pass through the model.
75 // We don't want to unwrap the Scope. 71 // We don't want to unwrap the Scope.
76 // TODO(jmesserly): a custom element extending <template> could notice this 72 // TODO(jmesserly): a custom element extending <template> could notice this
77 // behavior. An alternative is to associate the Scope with the node via an 73 // behavior. An alternative is to associate the Scope with the node via an
78 // Expando, which is what the JavaScript PolymerExpressions does. 74 // Expando, which is what the JavaScript PolymerExpressions does.
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 Expression _expr; 107 Expression _expr;
112 Function _callback; 108 Function _callback;
113 StreamSubscription _sub; 109 StreamSubscription _sub;
114 var _value; 110 var _value;
115 111
116 _Binding(this._expr, this._scope, [this._converter]); 112 _Binding(this._expr, this._scope, [this._converter]);
117 113
118 static _oneTime(Expression expr, Scope scope, [converter]) { 114 static _oneTime(Expression expr, Scope scope, [converter]) {
119 try { 115 try {
120 return _convertValue(eval(expr, scope), scope, converter); 116 return _convertValue(eval(expr, scope), scope, converter);
121 } on EvalException catch (e) { 117 } catch (e, s) {
122 _logger.warning("Error evaluating expression '$expr': ${e.message}"); 118 new Completer().completeError(
Jennifer Messerly 2014/03/21 20:08:54 nice!
123 return null; 119 "Error evaluating expression '$expr': $e", s);
124 } 120 }
121 return null;
125 } 122 }
126 123
127 _setValue(v) { 124 _setValue(v) {
128 _value = _convertValue(v, _scope, _converter); 125 _value = _convertValue(v, _scope, _converter);
129 if (_callback != null) _callback(_value); 126 if (_callback != null) _callback(_value);
130 } 127 }
131 128
132 static _convertValue(v, scope, converter) { 129 static _convertValue(v, scope, converter) {
133 if (v is Comprehension) { 130 if (v is Comprehension) {
134 // convert the Comprehension into a list of scopes with the loop 131 // convert the Comprehension into a list of scopes with the loop
135 // variable added to the scope 132 // variable added to the scope
136 return v.iterable.map((i) { 133 return v.iterable.map((i) => scope.childScope(v.identifier, i))
137 var vars = new Map(); 134 .toList(growable: false);
138 vars[v.identifier] = i;
139 Scope childScope = new Scope(parent: scope, variables: vars);
140 return childScope;
141 }).toList(growable: false);
142 } else { 135 } else {
143 return converter == null ? v : converter(v); 136 return converter == null ? v : converter(v);
144 } 137 }
145 } 138 }
146 139
147 get value { 140 get value {
148 if (_callback != null) return _value; 141 if (_callback != null) return _value;
149 return _oneTime(_expr, _scope, _converter); 142 return _oneTime(_expr, _scope, _converter);
150 } 143 }
151 144
152 set value(v) { 145 set value(v) {
153 try { 146 try {
154 assign(_expr, v, _scope); 147 assign(_expr, v, _scope);
155 } on EvalException catch (e) { 148 } catch (e, s) {
156 _logger.warning("Error evaluating expression '$_expr': ${e.message}"); 149 new Completer().completeError(
150 "Error evaluating expression '$_expr': $e", s);
157 } 151 }
158 } 152 }
159 153
160 open(callback(value)) { 154 open(callback(value)) {
161 if (_callback != null) throw new StateError('already open'); 155 if (_callback != null) throw new StateError('already open');
162 156
163 _callback = callback; 157 _callback = callback;
164 final expr = observe(_expr, _scope); 158 final expr = observe(_expr, _scope);
165 _expr = expr; 159 _expr = expr;
166 _sub = expr.onUpdate.listen(_setValue)..onError((e) { 160 _sub = expr.onUpdate.listen(_setValue)..onError((e, s) {
167 _logger.warning("Error evaluating expression '$_expr': ${e.message}"); 161 new Completer().completeError(
162 "Error evaluating expression '$expr': $e", s);
168 }); 163 });
169 try { 164 try {
170 update(expr, _scope); 165 update(expr, _scope);
171 _value = _convertValue(expr.currentValue, _scope, _converter); 166 _value = _convertValue(expr.currentValue, _scope, _converter);
172 } on EvalException catch (e) { 167 } catch (e, s) {
173 _logger.warning("Error evaluating expression '$_expr': ${e.message}"); 168 new Completer().completeError(
169 "Error evaluating expression '$expr': $e", s);
174 } 170 }
175 return _value; 171 return _value;
176 } 172 }
177 173
178 void close() { 174 void close() {
179 if (_callback == null) return; 175 if (_callback == null) return;
180 176
181 _sub.cancel(); 177 _sub.cancel();
182 _sub = null; 178 _sub = null;
183 _expr = (_expr as ExpressionObserver).expression; 179 _expr = (_expr as ExpressionObserver).expression;
184 _callback = null; 180 _callback = null;
185 } 181 }
186 } 182 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698