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

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

Issue 258503008: Support Dart debugger API directly (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 8 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 _Property {
8 _Property(this.name) :
9 _hasValue = false,
10 writable = false,
11 isMethod = false,
12 isOwn = true,
13 wasThrown = false;
14
15 bool get hasValue => _hasValue;
16 get value => _value;
17 set value(v) {
18 _value = v;
19 _hasValue = true;
20 }
21
22 final String name;
23 Function setter;
24 Function getter;
25 var _value;
26 bool _hasValue;
27 bool writable;
28 bool isMethod;
29 bool isOwn;
30 bool wasThrown;
31 }
32
7 class _ConsoleVariables { 33 class _ConsoleVariables {
8 Map<String, Object> _data = new Map<String, Object>(); 34 Map<String, Object> _data = new Map<String, Object>();
9 35
10 /** 36 /**
11 * Forward member accesses to the backing JavaScript object. 37 * Forward member accesses to the backing JavaScript object.
12 */ 38 */
13 noSuchMethod(Invocation invocation) { 39 noSuchMethod(Invocation invocation) {
14 String member = MirrorSystem.getName(invocation.memberName); 40 String member = MirrorSystem.getName(invocation.memberName);
15 if (invocation.isGetter) { 41 if (invocation.isGetter) {
16 return _data[member]; 42 return _data[member];
17 } else if (invocation.isSetter) { 43 } else if (invocation.isSetter) {
18 assert(member.endsWith('=')); 44 assert(member.endsWith('='));
19 member = member.substring(0, member.length - 1); 45 member = member.substring(0, member.length - 1);
20 _data[member] = invocation.positionalArguments[0]; 46 _data[member] = invocation.positionalArguments[0];
21 } else { 47 } else {
22 return Function.apply(_data[member], invocation.positionalArguments, invoc ation.namedArguments); 48 return Function.apply(_data[member], invocation.positionalArguments, invoc ation.namedArguments);
23 } 49 }
24 } 50 }
25 51
26 void clear() => _data.clear(); 52 void clear() => _data.clear();
27 53
28 /** 54 /**
29 * List all variables currently defined. 55 * List all variables currently defined.
30 */ 56 */
31 List variables() => _data.keys.toList(growable: false); 57 List variables() => _data.keys.toList(growable: false);
32 } 58 }
33 59
60 /**
61 * Base class for invocation trampolines used to closurize methods, getters
62 * and setters.
63 */
64 abstract class _Trampoline implements Function {
65 final ObjectMirror _receiver;
66 final MethodMirror _methodMirror;
67 final Symbol _selector;
68
69 _Trampoline(this._receiver, this._methodMirror, this._selector);
70 }
71
72 class _MethodTrampoline extends _Trampoline {
73 _MethodTrampoline(ObjectMirror receiver, MethodMirror methodMirror, Symbol sel ector) :
Leaf 2014/05/07 01:47:27 line width?
Jacob 2014/05/07 20:57:08 Done.
74 super(receiver, methodMirror, selector);
75
76 noSuchMethod(Invocation msg) {
77 if (msg.memberName != #call) return super.noSuchMethod(msg);
78 return _receiver.invoke(_selector,
79 msg.positionalArguments,
80 msg.namedArguments).reflectee;
81 }
82 }
83
84 /**
85 * Invocation trampoline class used to closurize getters.
86 */
87 class _GetterTrampoline extends _Trampoline {
88 _GetterTrampoline(ObjectMirror receiver, MethodMirror methodMirror, Symbol sel ector) :
Leaf 2014/05/07 01:47:27 ditto
Jacob 2014/05/07 20:57:08 Done.
89 super(receiver, methodMirror, selector);
90
91 call() => _receiver.getField(_selector).reflectee;
92 }
93
94 /**
95 * Invocation trampoline class used to closurize setters.
96 */
97 class _SetterTrampoline extends _Trampoline {
98 _SetterTrampoline(ObjectMirror receiver, MethodMirror methodMirror, Symbol sel ector) :
Leaf 2014/05/07 01:47:27 also
Jacob 2014/05/07 20:57:08 Done.
99 super(receiver, methodMirror, selector);
100
101 call(value) {
102 _receiver.setField(_selector, value);
103 }
104 }
105
34 class _Utils { 106 class _Utils {
35 static double dateTimeToDouble(DateTime dateTime) => 107 static double dateTimeToDouble(DateTime dateTime) =>
36 dateTime.millisecondsSinceEpoch.toDouble(); 108 dateTime.millisecondsSinceEpoch.toDouble();
37 static DateTime doubleToDateTime(double dateTime) { 109 static DateTime doubleToDateTime(double dateTime) {
38 try { 110 try {
39 return new DateTime.fromMillisecondsSinceEpoch(dateTime.toInt()); 111 return new DateTime.fromMillisecondsSinceEpoch(dateTime.toInt());
40 } catch(_) { 112 } catch(_) {
41 // TODO(antonnm): treat exceptions properly in bindings and 113 // TODO(antonnm): treat exceptions properly in bindings and
42 // find out how to treat NaNs. 114 // find out how to treat NaNs.
43 return null; 115 return null;
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 var map = {}; 209 var map = {};
138 for (int i = 0; i < localVariables.length; i+=2) { 210 for (int i = 0; i < localVariables.length; i+=2) {
139 map[stripMemberName(localVariables[i])] = localVariables[i+1]; 211 map[stripMemberName(localVariables[i])] = localVariables[i+1];
140 } 212 }
141 return map; 213 return map;
142 } 214 }
143 215
144 static _ConsoleVariables _consoleTempVariables = new _ConsoleVariables(); 216 static _ConsoleVariables _consoleTempVariables = new _ConsoleVariables();
145 217
146 /** 218 /**
147 * Header passed in from the Dartium Developer Tools when an expression is
148 * evaluated in the console as opposed to the watch window or another context
149 * that does not expect REPL support.
150 */
151 static const _CONSOLE_API_SUPPORT_HEADER =
152 'with ((console && console._commandLineAPI) || { __proto__: null }) {\n';
153 static bool expectsConsoleApi(String expression) {
154 return expression.indexOf(_CONSOLE_API_SUPPORT_HEADER) == 0;;
155 }
156
157 /**
158 * Takes an [expression] and a list of [local] variable and returns an 219 * Takes an [expression] and a list of [local] variable and returns an
159 * expression for a closure with a body matching the original expression 220 * expression for a closure with a body matching the original expression
160 * where locals are passed in as arguments. Returns a list containing the 221 * where locals are passed in as arguments. Returns a list containing the
161 * String expression for the closure and the list of arguments that should 222 * String expression for the closure and the list of arguments that should
162 * be passed to it. The expression should then be evaluated using 223 * be passed to it. The expression should then be evaluated using
163 * Dart_EvaluateExpr which will generate a closure that should be invoked 224 * Dart_EvaluateExpr which will generate a closure that should be invoked
164 * with the list of arguments passed to this method. 225 * with the list of arguments passed to this method.
165 * 226 *
166 * For example: 227 * For example:
167 * <code> 228 * <code>
168 * _consoleTempVariables = {'a' : someValue, 'b': someOtherValue} 229 * _consoleTempVariables = {'a' : someValue, 'b': someOtherValue}
169 * wrapExpressionAsClosure("${_CONSOLE_API_SUPPORT_HEADER}foo + bar + a", 230 * wrapExpressionAsClosure("foo + bar + a", ["bar", 40, "foo", 2], true)
170 * ["bar", 40, "foo", 2])
171 * </code> 231 * </code>
172 * will return: 232 * will return:
173 * <code> 233 * <code>
174 * ["""(final $consoleVariables, final bar, final foo, final a, final b) => 234 * ["""(final $consoleVariables, final bar, final foo, final a, final b) =>
175 * (foo + bar + a 235 * (foo + bar + a
176 * )""", 236 * )""",
177 * [_consoleTempVariables, 40, 2, someValue, someOtherValue]] 237 * [_consoleTempVariables, 40, 2, someValue, someOtherValue]]
178 * </code> 238 * </code>
179 */ 239 */
180 static List wrapExpressionAsClosure(String expression, List locals) { 240 static List wrapExpressionAsClosure(String expression, List locals,
181 // FIXME: dartbug.com/10434 find a less fragile way to determine whether 241 bool includeCommandLineAPI) {
182 // we need to strip off console API support added by InjectedScript.
183 var args = {}; 242 var args = {};
184 var sb = new StringBuffer("("); 243 var sb = new StringBuffer("(");
185 addArg(arg, value) { 244 addArg(arg, value) {
186 arg = stripMemberName(arg); 245 arg = stripMemberName(arg);
187 if (args.containsKey(arg)) return; 246 if (args.containsKey(arg)) return;
188 // We ignore arguments with the name 'this' rather than throwing an 247 // We ignore arguments with the name 'this' rather than throwing an
189 // exception because Dart_GetLocalVariables includes 'this' and it 248 // exception because Dart_GetLocalVariables includes 'this' and it
190 // is more convenient to filter it out here than from C++ code. 249 // is more convenient to filter it out here than from C++ code.
191 // 'this' needs to be handled by calling Dart_EvaluateExpr with 250 // 'this' needs to be handled by calling Dart_EvaluateExpr with
192 // 'this' as the target rather than by passing it as an argument. 251 // 'this' as the target rather than by passing it as an argument.
193 if (arg == 'this') return; 252 if (arg == 'this') return;
194 if (args.isNotEmpty) { 253 if (args.isNotEmpty) {
195 sb.write(", "); 254 sb.write(", ");
196 } 255 }
197 sb.write("final $arg"); 256 sb.write("final $arg");
198 args[arg] = value; 257 args[arg] = value;
199 } 258 }
200 259
201 if (expectsConsoleApi(expression)) { 260 if (includeCommandLineAPI) {
202 expression = expression.substring(expression.indexOf('\n') + 1);
203 expression = expression.substring(0, expression.lastIndexOf('\n'));
204
205 addArg("\$consoleVariables", _consoleTempVariables); 261 addArg("\$consoleVariables", _consoleTempVariables);
206 262
207 // FIXME: use a real Dart tokenizer. The following regular expressions 263 // FIXME: use a real Dart tokenizer. The following regular expressions
208 // only allow setting variables at the immediate start of the expression 264 // only allow setting variables at the immediate start of the expression
209 // to limit the number of edge cases we have to handle. 265 // to limit the number of edge cases we have to handle.
210 266
211 // Match expressions that start with "var x" 267 // Match expressions that start with "var x"
212 final _VARIABLE_DECLARATION = new RegExp("^(\\s*)var\\s+(\\w+)"); 268 final _VARIABLE_DECLARATION = new RegExp("^(\\s*)var\\s+(\\w+)");
213 // Match expressions that start with "someExistingConsoleVar =" 269 // Match expressions that start with "someExistingConsoleVar ="
214 final _SET_VARIABLE = new RegExp("^(\\s*)(\\w+)(\\s*=)"); 270 final _SET_VARIABLE = new RegExp("^(\\s*)(\\w+)(\\s*=)");
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 307
252 // TODO(jacobr): remove the parentheses around the expresson once 308 // TODO(jacobr): remove the parentheses around the expresson once
253 // dartbug.com/13723 is fixed. Currently we wrap expression in parentheses 309 // dartbug.com/13723 is fixed. Currently we wrap expression in parentheses
254 // to ensure only valid Dart expressions are allowed. Otherwise the DartVM 310 // to ensure only valid Dart expressions are allowed. Otherwise the DartVM
255 // quietly ignores trailing Dart statements resulting in user confusion 311 // quietly ignores trailing Dart statements resulting in user confusion
256 // when part of an invalid expression they entered is ignored. 312 // when part of an invalid expression they entered is ignored.
257 sb..write(') => (\n$expression\n)'); 313 sb..write(') => (\n$expression\n)');
258 return [sb.toString(), args.values.toList(growable: false)]; 314 return [sb.toString(), args.values.toList(growable: false)];
259 } 315 }
260 316
261 /** 317 static String _getShortSymbolName(Symbol symbol,
262 * TODO(jacobr): this is a big hack to get around the fact that we are still 318 DeclarationMirror declaration) {
263 * passing some JS expression to the evaluate method even when in a Dart 319 var name = MirrorSystem.getName(symbol);
264 * context. 320 if (declaration is MethodMirror) {
265 */ 321 if (declaration.isSetter && name[name.length-1] == "=") {
266 static bool isJsExpression(String expression) => 322 return name.substring(0, name.length-1);
267 expression.startsWith("(function getCompletions"); 323 }
268 324 if (declaration.isConstructor) {
269 /** 325 return name.substring(name.indexOf('.') + 1);
270 * Returns a list of completions to use if the receiver is o. 326 }
271 */ 327 }
272 static List<String> getCompletions(o) { 328 return name;
273 MirrorSystem system = currentMirrorSystem(); 329 }
274 var completions = new Set<String>(); 330
275 addAll(Map<Symbol, dynamic> map, bool isStatic) { 331 /**
276 map.forEach((symbol, mirror) { 332 * Adds all candidate String completitions from [declarations] to [output]
277 if (mirror.isStatic == isStatic && !mirror.isPrivate) { 333 * filtering based on [staticContext] and [includePrivate].
334 */
335 static void _getCompletionsHelper(ClassMirror classMirror,
336 bool staticContext, bool includePrivate, Set<String> output) {
337 classMirror.declarations.forEach((symbol, declaration) {
338 if (!includePrivate && declaration.isPrivate) return;
339 if (declaration is VariableMirror) {
340 if (staticContext != declaration.isStatic) return;
341 } else if (declaration is MethodMirror) {
342 if (staticContext != declaration.isStatic) return;
rmacnak 2014/05/06 21:14:43 Should do this check after considering constructor
Jacob 2014/05/07 00:05:24 Good catch! I added a test (see utils.dart in the
343 if (declaration.isOperator) return;
rmacnak 2014/05/06 21:14:43 Because the completions assume dot notation?
Jacob 2014/05/07 00:05:24 Correct. Completions are after a dot.
344 if (declaration.isConstructor) {
345 var name = MirrorSystem.getName(declaration.constructorName);
346 if (name.isNotEmpty) output.add(name);
347 return;
348 }
349 } else if (declaration is TypeMirror) {
350 return;
351 }
352 output.add(_getShortSymbolName(symbol, declaration));
353 });
354 }
355
356 static void _getLibraryCompletionsHelper(
357 LibraryMirror library, bool includePrivate, Set<String> output) {
358 library.declarations.forEach((symbol, declaration) {
rmacnak 2014/05/06 21:14:43 Add the prefixed imports (but not their declaratio
Jacob 2014/05/07 00:05:24 Correct. Interesting idea to show all completions.
359 if (!includePrivate && declaration.isPrivate) return;
360 output.add(_getShortSymbolName(symbol, declaration));
361 });
362 }
363
364 static LibraryMirror getLibraryMirror(String url) =>
365 currentMirrorSystem().libraries[Uri.parse(url)];
366
367 /**
368 * Get code completions for [o] only showing privates from [libraryUrl].
369 */
370 static List<String> getObjectCompletions(o, String libraryUrl) {
371 var classMirror;
372 bool staticContext;
373 if (o is Type) {
374 classMirror = reflectClass(o);
375 staticContext = true;
376 } else {
377 classMirror = reflect(o).type;
378 staticContext = false;
379 }
380 var names = new Set<String>();
381 getClassCompletions(classMirror, names, staticContext, libraryUrl);
382 return names.toList()..sort();
383 }
384
385 static void getClassCompletions(ClassMirror classMirror, Set<String> names,
386 bool staticContext, String libraryUrl) {
387 LibraryMirror libraryMirror = getLibraryMirror(libraryUrl);
388 if (!staticContext) {
389 for (var interface in classMirror.superinterfaces) {
rmacnak 2014/05/06 21:14:43 Interfaces declared on superclasses?
Jacob 2014/05/07 00:05:24 Fixed.
390 _getCompletionsHelper(interface, staticContext,
391 libraryMirror == interface.owner, names);
392 }
393 }
394 while (classMirror != null) {
395 _getCompletionsHelper(classMirror, staticContext,
396 libraryMirror == classMirror.owner, names);
397 // Do not walk up the superclass tree when displaying statics.
398 if (staticContext) break;
399 classMirror = classMirror.superclass;
400 }
401 }
402
403 static List<String> getLibraryCompletions(String url) {
404 var names = new Set<String>();
405 _getLibraryCompletionsHelper(getLibraryMirror(url), true, names);
406 return names.toList();
407 }
408
409 /**
410 * Get valid code completitions from within a library and all libraries
411 * imported by that library.
412 */
413 static List<String> getLibraryCompletionsIncludingImports(String url) {
414 var names = new Set<String>();
415 var libraryMirror = getLibraryMirror(url);
416 _getLibraryCompletionsHelper(libraryMirror, true, names);
417 for (var dependency in libraryMirror.libraryDependencies) {
418 if (dependency.isImport) {
419 if (dependency.prefix == null) {
420 _getLibraryCompletionsHelper(dependency.targetLibrary, false, names);
421 } else {
422 names.add(MirrorSystem.getName(dependency.prefix));
423 }
424 }
425 }
426 return names.toList();
427 }
428
429 /**
430 * For parity with the JavaScript debugger, we treat some getters as if
431 * they are fields so that users can see their values immediately.
432 * This matches JavaScript's behavior for getters on DOM objects.
433 * In the future we should consider adding an annotation to tag getters
434 * in user libraries as side effect free.
435 */
436 static bool _isSideEffectFreeGetter(MethodMirror methodMirror) {
437 var owner = methodMirror.owner;
438 var libraryMirror;
439 if (owner is ClassMirror) {
440 libraryMirror = owner.owner;
Leaf 2014/05/07 01:47:27 Does this do the right thing if the class is produ
rmacnak 2014/05/07 16:59:51 A class's owner will always be a library.
Jacob 2014/05/07 20:57:08 yep.
441 } else if (owner is LibraryMirror) {
442 libraryMirror = owner;
443 }
444 if (libraryMirror != null) {
445 var libraryUrl = MirrorSystem.getName(libraryMirror.qualifiedName);
rmacnak 2014/05/06 21:14:43 You're not comparing the url here. The qualified n
Jacob 2014/05/07 00:05:24 Tweaked to actually use the URI instead.
446 // This matches JavaScript behavior. We should consider displaying
447 // getters for all dart platform libraries rather than just dart.dom.
rmacnak 2014/05/06 21:14:43 I wouldn't do this for all Dart platform libraries
Jacob 2014/05/07 00:05:24 Makes sense. I think the right solution is to pro
448 if (libraryUrl.startsWith("dart.dom."))
449 return true;
450 }
451 return false;
452 }
453
454 /**
455 * Whether we should treat a property as a field for the purposes of the
456 * debugger.
457 */
458 static bool treatPropertyAsField(MethodMirror methodMirror) =>
459 (methodMirror.isGetter || methodMirror.isSetter) &&
460 (methodMirror.isSynthetic || _isSideEffectFreeGetter(methodMirror));
461
462 // TODO(jacobr): generate more concise function descriptions instead of
463 // dumping the entire function source.
464 static String describeFunction(function) {
465 if (function is _Trampoline) return function._methodMirror.source;
466 try {
467 return reflect(function).function.source;
468 } catch (e) {
469 return function.toString();
470 }
471 }
472
473 static List getInvocationTrampolineDetails(_Trampoline method) {
474 var loc = method._methodMirror.location;
475 return [loc.line, loc.column, loc.sourceUri.toString(),
476 MirrorSystem.getName(method._selector)];
477 }
478
479 static List getLibraryProperties(String libraryUrl, bool ownProperties,
480 bool accessorPropertiesOnly) {
481 var properties = new Map<String, _Property>();
482 var libraryMirror = getLibraryMirror(libraryUrl);
483 _addInstanceMirrors(libraryMirror, libraryMirror,
484 libraryMirror.declarations,
485 ownProperties, accessorPropertiesOnly, false, false,
486 properties);
487 if (!accessorPropertiesOnly) {
488 // We need to add class properties for all classes in the library.
489 libraryMirror.declarations.forEach((symbol, declarationMirror) {
490 if (declarationMirror is ClassMirror) {
278 var name = MirrorSystem.getName(symbol); 491 var name = MirrorSystem.getName(symbol);
279 if (mirror is MethodMirror && mirror.isSetter) 492 if (declarationMirror.hasReflectedType
280 name = name.substring(0, name.length - 1); 493 && !properties.containsKey(name)) {
281 completions.add(name); 494 properties[name] = new _Property(name)
495 ..value = declarationMirror.reflectedType;
Leaf 2014/05/07 01:47:27 Is this idiomatic in Dart? I'm presuming that thi
Jacob 2014/05/07 20:57:08 This is the idiomatic way to use Dart cascades. A
Leaf 2014/05/08 04:04:01 Ok, I'll get used to it. On 2014/05/07 20:57:08,
496 }
282 } 497 }
283 }); 498 });
284 } 499 }
285 500 return packageProperties(properties);
286 addForClass(ClassMirror mirror, bool isStatic) { 501 }
287 if (mirror == null) 502
503 static List getObjectProperties(o, bool ownProperties,
504 bool accessorPropertiesOnly) {
505 var properties = new Map<String, _Property>();
506 var names = new Set<String>();
507 var objectMirror = reflect(o);
508 var classMirror = objectMirror.type;
509 _addInstanceMirrors(objectMirror, classMirror.owner,
Leaf 2014/05/07 01:47:27 Same question as before about class mirror owners
Jacob 2014/05/07 20:57:08 Same answer as before. the owner is a library.
510 classMirror.instanceMembers,
511 ownProperties, accessorPropertiesOnly, false, true,
512 properties);
513 return packageProperties(properties);
514 }
515
516 static List getObjectClassProperties(o, bool ownProperties,
517 bool accessorPropertiesOnly) {
518 var properties = new Map<String, _Property>();
519 var objectMirror = reflect(o);
520 var classMirror = objectMirror.type;
521 _addInstanceMirrors(objectMirror, classMirror.owner,
Leaf 2014/05/07 01:47:27 ditto
Jacob 2014/05/07 20:57:08 same answer as other case.
522 classMirror.instanceMembers,
523 ownProperties, accessorPropertiesOnly, true, false,
524 properties);
525 _addStatics(classMirror, properties, accessorPropertiesOnly);
526 return packageProperties(properties);
527 }
528
529 static List getClassProperties(Type t, bool ownProperties,
530 bool accessorPropertiesOnly) {
531 var properties = new Map<String, _Property>();
532 var classMirror = reflectClass(t);
533 _addStatics(classMirror, properties, accessorPropertiesOnly);
534 return packageProperties(properties);
535 }
536
537 static void _addStatics(ClassMirror classMirror,
538 Map<String, _Property> properties,
539 bool accessorPropertiesOnly) {
540 classMirror.declarations.forEach((symbol, declaration) {
541 var name = _getShortSymbolName(symbol, declaration);
542 if (declaration is VariableMirror) {
543 if (accessorPropertiesOnly) return;
544 if (!declaration.isStatic) return;
545 properties.putIfAbsent(name, () => new _Property(name))
546 ..value = classMirror.getField(symbol).reflectee
547 ..writable = declaration.isFinal && !declaration.isConst;
Leaf 2014/05/07 01:47:27 I don't understand this line (possibly my fault).
Jacob 2014/05/07 20:57:08 I don't understand what I was thinking either. The
548 } else if (declaration is MethodMirror) {
549 MethodMirror methodMirror = declaration;
550 // FIXMEDART: should we display constructors?
551 if (methodMirror.isConstructor) return;
552 if (!methodMirror.isStatic) return;
553 if (accessorPropertiesOnly) {
554 if (methodMirror.isRegularMethod ||
555 treatPropertyAsField(methodMirror)) {
556 return;
557 }
558 } else if (!methodMirror.isRegularMethod &&
559 !treatPropertyAsField(methodMirror)) {
560 return;
561 }
562 var property = properties.putIfAbsent(name, () => new _Property(name));
Leaf 2014/05/07 01:47:27 I'm not sure I get why this is right. If I unders
rmacnak 2014/05/07 16:59:51 Implicit getters and setters are not part of Class
Jacob 2014/05/07 20:57:08 Correct. That is why I have to add these cases.
563 if (methodMirror.isRegularMethod) {
564 property
565 ..value = new _MethodTrampoline(classMirror, methodMirror, symbol)
566 ..isMethod = true;
567 } else if (methodMirror.isGetter) {
568 if (treatPropertyAsField(methodMirror)) {
569 try {
570 property.value = classMirror.getField(symbol).reflectee;
571 } catch (e) {
572 property
573 ..wasThrown = true
574 ..value = e;
575 }
576 } else if (accessorPropertiesOnly) {
577 property.getter = new _GetterTrampoline(classMirror,
578 methodMirror, symbol);
579 }
580 } else if (methodMirror.isSetter) {
581 if (accessorPropertiesOnly && !treatPropertyAsField(methodMirror)) {
582 property.setter = new _SetterTrampoline(classMirror,
583 methodMirror, classMirror.owner);
584 }
585 property.writable = true;
586 }
587 }
588 });
589 }
590
591 /**
592 * Helper method that handles collecting up properties from classes
593 * or libraries using the filters [ownProperties], [accessorPropertiesOnly],
594 * [hideFields], and [hideMethods] to determine which properties are
595 * collected. [accessorPropertiesOnly] specifies whether all properties
596 * should be returned or just accessors. [hideFields] specifies whether
597 * fields should be hidden. hideMethods specifies whether methods should be
598 * shown or hidden. [ownProperties] is not currently used but is part of the
599 * Blink devtools API for enumerating properties.
600 */
601 static void _addInstanceMirrors(
602 ObjectMirror objectMirror,
603 LibraryMirror libraryMirror,
604 Map<Symbol, Mirror> declarations,
605 bool ownProperties, bool accessorPropertiesOnly,
606 bool hideFields, bool hideMethods,
607 Map<String, _Property> properties) {
608 declarations.forEach((Symbol symbol, Mirror declaration) {
609 if (declaration is TypedefMirror || declaration is ClassMirror) return;
610 var name = _getShortSymbolName(symbol, declaration);
611 bool isField = declaration is VariableMirror ||
612 (declaration is MethodMirror && treatPropertyAsField(declaration));
613 if ((isField && hideFields) || (hideMethods && !isField)) return;
614 if (accessorPropertiesOnly) {
615 if (declaration is ClassMirror || declaration is VariableMirror ||
Leaf 2014/05/07 01:47:27 declaration is known not to be ClassMirror here.
Jacob 2014/05/07 20:57:08 Fixed. I originally tried to use this method for b
616 declaration.isRegularMethod || isField) {
617 return;
618 }
619 } else if (declaration is MethodMirror &&
620 (declaration.isGetter || declaration.isSetter) &&
621 !treatPropertyAsField(declaration)) {
288 return; 622 return;
289 addAll(mirror.declarations, isStatic); 623 }
290 if (mirror.superclass != null) 624 var property = properties.putIfAbsent(name, () => new _Property(name));
291 addForClass(mirror.superclass, isStatic); 625 if (declaration is VariableMirror) {
292 for (var interface in mirror.superinterfaces) { 626 property.value = objectMirror.getField(symbol).reflectee;
293 addForClass(interface, isStatic); 627 property.writable = !declaration.isFinal && !declaration.isConst;
294 } 628 } else if (declaration is ClassMirror) {
Leaf 2014/05/07 01:47:27 Again, known to be false.
Jacob 2014/05/07 20:57:08 Done.
295 } 629 property.value = declaration.runtimeType;
296 630 } else if (declaration.isRegularMethod) {
Leaf 2014/05/07 01:47:27 The section from here to the end is pretty close t
Jacob 2014/05/07 20:57:08 Done.
297 if (o is Type) { 631 property.value = new _MethodTrampoline(objectMirror,
298 addForClass(reflectClass(o), true); 632 declaration, symbol);
299 } else { 633 property.isMethod = true;
300 addForClass(reflect(o).type, false); 634 } else if (declaration.isGetter) {
301 } 635 if (treatPropertyAsField(declaration)) {
302 return completions.toList(growable: false); 636 try {
303 } 637 property.value = objectMirror.getField(symbol).reflectee;
304 638 } catch (e) {
305 /** 639 property
640 ..wasThrown = true
641 ..value = e;
642 }
643 } else if (accessorPropertiesOnly) {
644 property.getter = new _GetterTrampoline(objectMirror,
645 declaration, symbol);
646 }
647 } else if (declaration.isSetter) {
648 property.writable = true;
649 if (accessorPropertiesOnly && !treatPropertyAsField(declaration)) {
650 property.setter = new _SetterTrampoline(objectMirror,
651 declaration, MirrorSystem.getSymbol(name, libraryMirror));
652 }
653 }
654 });
655 }
656
657 /**
658 * Flatten down the properties data structure into a List that is easy to
659 * access from native code.
660 */
661 static List packageProperties(Map<String, _Property> properties) {
662 var ret = [];
663 for (var property in properties.values) {
664 ret.addAll([property.name,
665 property.setter,
666 property.getter,
667 property.value,
668 property.hasValue,
669 property.writable,
670 property.isMethod,
671 property.isOwn,
672 property.wasThrown]);
673 }
674 return ret;
675 }
676
677 /**
678 * Get a property, returning null if the property does not exist.
679 * For private property names, we attempt to resolve the property in the
680 * context of each library that the property name could be associated with.
681 */
682 static getObjectPropertySafe(o, String propertyName) {
683 var objectMirror = reflect(o);
684 var classMirror = objectMirror.type;
685 if (propertyName.startsWith("_")) {
686 var attemptedLibraries = new Set<LibraryMirror>();
687 while (classMirror != null) {
688 LibraryMirror library = classMirror.owner;
689 if (!attemptedLibraries.contains(library)) {
690 try {
691 return objectMirror.getField(
692 MirrorSystem.getSymbol(propertyName, library)).reflectee;
693 } catch (e) { }
694 attemptedLibraries.add(library);
695 }
696 classMirror = classMirror.superclass;
697 }
698 return null;
699 }
700 try {
701 return objectMirror.getField(
702 MirrorSystem.getSymbol(propertyName)).reflectee;
703 } catch (e) {
704 return null;
705 }
706 }
707
708 /**
306 * Convenience helper to get the keys of a [Map] as a [List]. 709 * Convenience helper to get the keys of a [Map] as a [List].
307 */ 710 */
308 static List getMapKeyList(Map map) => map.keys.toList(); 711 static List getMapKeyList(Map map) => map.keys.toList();
309 712
310 /** 713 /**
311 * Returns the keys of an arbitrary Dart Map encoded as unique Strings. 714 * Returns the keys of an arbitrary Dart Map encoded as unique Strings.
312 * Keys that are strings are left unchanged except that the prefix ":" is 715 * Keys that are strings are left unchanged except that the prefix ":" is
313 * added to disambiguate keys from other Dart members. 716 * added to disambiguate keys from other Dart members.
314 * Keys that are not strings have # followed by the index of the key in the ma p 717 * Keys that are not strings have # followed by the index of the key in the ma p
315 * prepended to disambuguate. This scheme is simplistic but easy to encode and 718 * prepended to disambuguate. This scheme is simplistic but easy to encode and
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
596 _scheduleImmediateHelper._schedule(callback); 999 _scheduleImmediateHelper._schedule(callback);
597 }; 1000 };
598 1001
599 get _pureIsolateScheduleImmediateClosure => ((void callback()) => 1002 get _pureIsolateScheduleImmediateClosure => ((void callback()) =>
600 throw new UnimplementedError("scheduleMicrotask in background isolates " 1003 throw new UnimplementedError("scheduleMicrotask in background isolates "
601 "are not supported in the browser")); 1004 "are not supported in the browser"));
602 1005
603 void _initializeCustomElement(Element e) { 1006 void _initializeCustomElement(Element e) {
604 _Utils.initializeCustomElement(e); 1007 _Utils.initializeCustomElement(e);
605 } 1008 }
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