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

Side by Side Diff: tools/dom/src/native_DOMImplementation.dart

Issue 25570002: Support defining console variables with var consoleVar = someValue syntax (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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 part of html; 5 part of html;
6 6
7 class _ConsoleVariables { 7 class _ConsoleVariables {
8 Map<String, Object> _data = new Map<String, Object>(); 8 Map<String, Object> _data = new Map<String, Object>();
9 9
10 /** 10 /**
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 */ 133 */
134 static Map<String, dynamic> createLocalVariablesMap(List localVariables) { 134 static Map<String, dynamic> createLocalVariablesMap(List localVariables) {
135 var map = {}; 135 var map = {};
136 for (int i = 0; i < localVariables.length; i+=2) { 136 for (int i = 0; i < localVariables.length; i+=2) {
137 map[stripMemberName(localVariables[i])] = localVariables[i+1]; 137 map[stripMemberName(localVariables[i])] = localVariables[i+1];
138 } 138 }
139 return map; 139 return map;
140 } 140 }
141 141
142 static _ConsoleVariables _consoleTempVariables = new _ConsoleVariables(); 142 static _ConsoleVariables _consoleTempVariables = new _ConsoleVariables();
143
144 /**
145 * Header passed in from the Dartium Developer Tools when an expression is
146 * evaluated in the console as opposed to the watch window or another context
147 * that does not expect REPL support.
148 */
149 static const _CONSOLE_API_SUPPORT_HEADER =
150 'with ((this && this.console && this.console._commandLineAPI) || {}) {\n';
151
143 /** 152 /**
144 * Takes an [expression] and a list of [local] variable and returns an 153 * Takes an [expression] and a list of [local] variable and returns an
145 * expression for a closure with a body matching the original expression 154 * expression for a closure with a body matching the original expression
146 * where locals are passed in as arguments. Returns a list containing the 155 * where locals are passed in as arguments. Returns a list containing the
147 * String expression for the closure and the list of arguments that should 156 * String expression for the closure and the list of arguments that should
148 * be passed to it. The expression should then be evaluated using 157 * be passed to it. The expression should then be evaluated using
149 * Dart_EvaluateExpr which will generate a closure that should be invoked 158 * Dart_EvaluateExpr which will generate a closure that should be invoked
150 * with the list of arguments passed to this method. 159 * with the list of arguments passed to this method.
151 * 160 *
152 * For example: 161 * For example:
153 * <code>wrapExpressionAsClosure("foo + bar", ["bar", 40, "foo", 2])</code> 162 * <code>
163 * _consoleTempVariables = {'a' : someValue, 'b': someOtherValue}
164 * wrapExpressionAsClosure("${_CONSOLE_API_SUPPORT_HEADER}foo + bar + a",
165 * ["bar", 40, "foo", 2])
166 * </code>
154 * will return: 167 * will return:
155 * <code>["(final $var, final bar, final foo) => foo + bar", [40, 2]]</code> 168 * <code>
169 * ["""(final $consoleVariables, final bar, final foo, final a, final b) =>
170 * (foo + bar + a
171 * )""",
172 * [_consoleTempVariables, 40, 2, someValue, someOtherValue]]
173 * </code>
156 */ 174 */
157 static List wrapExpressionAsClosure(String expression, List locals) { 175 static List wrapExpressionAsClosure(String expression, List locals) {
176 // FIXME: dartbug.com/10434 find a less fragile way to determine whether
177 // we need to strip off console API support added by InjectedScript.
158 var args = {}; 178 var args = {};
159 var sb = new StringBuffer("("); 179 var sb = new StringBuffer("(");
160 addArg(arg, value) { 180 addArg(arg, value) {
161 arg = stripMemberName(arg); 181 arg = stripMemberName(arg);
162 if (args.containsKey(arg)) return; 182 if (args.containsKey(arg)) return;
163 // We ignore arguments with the name 'this' rather than throwing an 183 // We ignore arguments with the name 'this' rather than throwing an
164 // exception because Dart_GetLocalVariables includes 'this' and it 184 // exception because Dart_GetLocalVariables includes 'this' and it
165 // is more convenient to filter it out here than from C++ code. 185 // is more convenient to filter it out here than from C++ code.
166 // 'this' needs to be handled by calling Dart_EvaluateExpr with 186 // 'this' needs to be handled by calling Dart_EvaluateExpr with
167 // 'this' as the target rather than by passing it as an argument. 187 // 'this' as the target rather than by passing it as an argument.
168 if (arg == 'this') return; 188 if (arg == 'this') return;
169 if (args.isNotEmpty) { 189 if (args.isNotEmpty) {
170 sb.write(", "); 190 sb.write(", ");
171 } 191 }
172 sb.write("final $arg"); 192 sb.write("final $arg");
173 args[arg] = value; 193 args[arg] = value;
174 } 194 }
175 195
176 addArg("\$var", _consoleTempVariables); 196 if (expression.indexOf(_CONSOLE_API_SUPPORT_HEADER) == 0) {
197 expression = expression.substring(expression.indexOf('\n') + 1);
198 expression = expression.substring(0, expression.lastIndexOf('\n'));
177 199
178 for (int i = 0; i < locals.length; i+= 2) { 200 addArg("\$consoleVariables", _consoleTempVariables);
179 addArg(locals[i], locals[i+1]); 201
202 // FIXME: use a real Dart tokenizer. The following regular expressions
203 // only allow setting variables at the immediate start of the expression
204 // to limit the number of edge cases we have to handle.
205
206 // Match expressions that start with "var x"
207 final _VARIABLE_DECLARATION = new RegExp("^(\\s*)var\\s+(\\w+)");
208 // Match expressions that start with "someExistingConsoleVar ="
209 final _SET_VARIABLE = new RegExp("^(\\s*)(\\w+)(\\s*=)");
210 // Match trailing semicolons.
211 final _ENDING_SEMICOLONS = new RegExp("(;\\s*)*\$");
212 expression = expression.replaceAllMapped(_VARIABLE_DECLARATION,
213 (match) {
214 var variableName = match[2];
215 // Set the console variable if it isn't already set.
216 if (!_consoleTempVariables._data.containsKey(variableName)) {
217 _consoleTempVariables._data[variableName] = null;
218 }
219 return "${match[1]}\$consoleVariables.${variableName}";
220 });
221
222 expression = expression.replaceAllMapped(_SET_VARIABLE,
223 (match) {
224 var variableName = match[2];
225 // Only rewrite if the name matches an existing console variable.
226 if (_consoleTempVariables._data.containsKey(variableName)) {
227 return "${match[1]}\$consoleVariables.${variableName}${match[3]}";
228 } else {
229 return match[0];
230 }
231 });
232
233 // We only allow dart expressions not Dart statements. Silently remove
234 // trailing semicolons the user might have added by accident to reduce the
235 // number of spurious compile errors.
236 expression = expression.replaceFirst(_ENDING_SEMICOLONS, "");
180 } 237 }
181 sb..write(')=>\n$expression'); 238
239 if (locals != null) {
240 for (int i = 0; i < locals.length; i+= 2) {
241 addArg(locals[i], locals[i+1]);
242 }
243 }
244 // Inject all the already defined console variables.
245 _consoleTempVariables._data.forEach(addArg);
246
247 // TODO(jacobr): remove the parentheses around the expresson once
248 // dartbug.com/13723 is fixed. Currently we wrap expression in parentheses
249 // to ensure only valid Dart expressions are allowed. Otherwise the DartVM
250 // quietly ignores trailing Dart statements resulting in user confusion
251 // when part of an invalid expression they entered is ignored.
252 sb..write(') => (\n$expression\n)');
182 return [sb.toString(), args.values.toList(growable: false)]; 253 return [sb.toString(), args.values.toList(growable: false)];
183 } 254 }
184 255
185 /** 256 /**
257 * TODO(jacobr): this is a big hack to get around the fact that we are still
258 * passing some JS expression to the evaluate method even when in a Dart
259 * context.
260 */
261 static bool isJsExpression(String expression) =>
262 expression.startsWith("(function getCompletions");
263
264 /**
265 * Returns a list of completions to use if the receiver is o.
266 */
267 static List<String> getCompletions(o) {
268 MirrorSystem system = currentMirrorSystem();
269 var completions = new Set<String>();
270 addAll(Map<Symbol, dynamic> map, bool isStatic) {
271 map.forEach((symbol, mirror) {
272 if (mirror.isStatic == isStatic && !mirror.isPrivate) {
273 var name = MirrorSystem.getName(symbol);
274 if (mirror is MethodMirror && mirror.isSetter)
275 name = name.substring(0, name.length - 1);
276 completions.add(name);
277 }
278 });
279 }
280
281 addForClass(ClassMirror mirror, bool isStatic) {
282 if (mirror == null)
283 return;
284 addAll(mirror.members, isStatic);
285 if (mirror.superclass != null)
286 addForClass(mirror.superclass, isStatic);
287 for (var interface in mirror.superinterfaces) {
288 addForClass(interface, isStatic);
289 }
290 }
291
292 if (o is Type) {
293 addForClass(reflectClass(o), true);
294 } else {
295 addForClass(reflect(o).type, false);
296 }
297 return completions.toList(growable: false);
298 }
299
300 /**
186 * Convenience helper to get the keys of a [Map] as a [List]. 301 * Convenience helper to get the keys of a [Map] as a [List].
187 */ 302 */
188 static List getMapKeyList(Map map) => map.keys.toList(); 303 static List getMapKeyList(Map map) => map.keys.toList();
189 304
190 /** 305 /**
191 * Returns the keys of an arbitrary Dart Map encoded as unique Strings. 306 * Returns the keys of an arbitrary Dart Map encoded as unique Strings.
192 * Keys that are strings are left unchanged except that the prefix ":" is 307 * Keys that are strings are left unchanged except that the prefix ":" is
193 * added to disambiguate keys from other Dart members. 308 * added to disambiguate keys from other Dart members.
194 * Keys that are not strings have # followed by the index of the key in the ma p 309 * Keys that are not strings have # followed by the index of the key in the ma p
195 * prepended to disambuguate. This scheme is simplistic but easy to encode and 310 * prepended to disambuguate. This scheme is simplistic but easy to encode and
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
510 _send(msg) { 625 _send(msg) {
511 _sendToHelperIsolate(msg, _sendPort); 626 _sendToHelperIsolate(msg, _sendPort);
512 } 627 }
513 628
514 bool get isActive => _isActive; 629 bool get isActive => _isActive;
515 } 630 }
516 631
517 get _pureIsolateTimerFactoryClosure => 632 get _pureIsolateTimerFactoryClosure =>
518 ((int milliSeconds, void callback(Timer time), bool repeating) => 633 ((int milliSeconds, void callback(Timer time), bool repeating) =>
519 new _PureIsolateTimer(milliSeconds, callback, repeating)); 634 new _PureIsolateTimer(milliSeconds, callback, repeating));
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698