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

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

Issue 258503008: Support Dart debugger API directly (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: ready Created 6 years, 6 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 | « tools/dom/idl/dart/dart.idl ('k') | 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,
49 invocation.namedArguments);
23 } 50 }
24 } 51 }
25 52
26 void clear() => _data.clear(); 53 void clear() => _data.clear();
27 54
28 /** 55 /**
29 * List all variables currently defined. 56 * List all variables currently defined.
30 */ 57 */
31 List variables() => _data.keys.toList(growable: false); 58 List variables() => _data.keys.toList();
59
60 void setVariable(String name, value) {
61 _data[name] = value;
62 }
63 }
64
65 /**
66 * Base class for invocation trampolines used to closurize methods, getters
67 * and setters.
68 */
69 abstract class _Trampoline implements Function {
70 final ObjectMirror _receiver;
71 final MethodMirror _methodMirror;
72 final Symbol _selector;
73
74 _Trampoline(this._receiver, this._methodMirror, this._selector);
75 }
76
77 class _MethodTrampoline extends _Trampoline {
78 _MethodTrampoline(ObjectMirror receiver, MethodMirror methodMirror,
79 Symbol selector) :
80 super(receiver, methodMirror, selector);
81
82 noSuchMethod(Invocation msg) {
83 if (msg.memberName != #call) return super.noSuchMethod(msg);
84 return _receiver.invoke(_selector,
85 msg.positionalArguments,
86 msg.namedArguments).reflectee;
87 }
88 }
89
90 /**
91 * Invocation trampoline class used to closurize getters.
92 */
93 class _GetterTrampoline extends _Trampoline {
94 _GetterTrampoline(ObjectMirror receiver, MethodMirror methodMirror,
95 Symbol selector) :
96 super(receiver, methodMirror, selector);
97
98 call() => _receiver.getField(_selector).reflectee;
99 }
100
101 /**
102 * Invocation trampoline class used to closurize setters.
103 */
104 class _SetterTrampoline extends _Trampoline {
105 _SetterTrampoline(ObjectMirror receiver, MethodMirror methodMirror,
106 Symbol selector) :
107 super(receiver, methodMirror, selector);
108
109 call(value) {
110 _receiver.setField(_selector, value);
111 }
32 } 112 }
33 113
34 class _Utils { 114 class _Utils {
35 static double dateTimeToDouble(DateTime dateTime) => 115 static double dateTimeToDouble(DateTime dateTime) =>
36 dateTime.millisecondsSinceEpoch.toDouble(); 116 dateTime.millisecondsSinceEpoch.toDouble();
37 static DateTime doubleToDateTime(double dateTime) { 117 static DateTime doubleToDateTime(double dateTime) {
38 try { 118 try {
39 return new DateTime.fromMillisecondsSinceEpoch(dateTime.toInt()); 119 return new DateTime.fromMillisecondsSinceEpoch(dateTime.toInt());
40 } catch(_) { 120 } catch(_) {
41 // TODO(antonnm): treat exceptions properly in bindings and 121 // TODO(antonnm): treat exceptions properly in bindings and
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 var map = {}; 217 var map = {};
138 for (int i = 0; i < localVariables.length; i+=2) { 218 for (int i = 0; i < localVariables.length; i+=2) {
139 map[stripMemberName(localVariables[i])] = localVariables[i+1]; 219 map[stripMemberName(localVariables[i])] = localVariables[i+1];
140 } 220 }
141 return map; 221 return map;
142 } 222 }
143 223
144 static _ConsoleVariables _consoleTempVariables = new _ConsoleVariables(); 224 static _ConsoleVariables _consoleTempVariables = new _ConsoleVariables();
145 225
146 /** 226 /**
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 in Dartium 34.
150 */
151 static const _CONSOLE_API_SUPPORT_HEADER_34 =
152 'with ((console && console._commandLineAPI) || { __proto__: null }) {\n';
153 /**
154 * Header passed in from the Dartium Developer Tools when an expression is
155 * evaluated in the console as opposed to the watch window or another context
156 * that does not expect REPL support in Dartium 35.
157 */
158 static const _CONSOLE_API_SUPPORT_HEADER_35 =
159 'with (__commandLineAPI || { __proto__: null }) {\n';
160
161
162 static bool expectsConsoleApi(String expression) {
163 return expression.indexOf(_CONSOLE_API_SUPPORT_HEADER_34) == 0 ||
164 expression.indexOf(_CONSOLE_API_SUPPORT_HEADER_35) == 0;
165 }
166
167 /**
168 * Takes an [expression] and a list of [local] variable and returns an 227 * Takes an [expression] and a list of [local] variable and returns an
169 * expression for a closure with a body matching the original expression 228 * expression for a closure with a body matching the original expression
170 * where locals are passed in as arguments. Returns a list containing the 229 * where locals are passed in as arguments. Returns a list containing the
171 * String expression for the closure and the list of arguments that should 230 * String expression for the closure and the list of arguments that should
172 * be passed to it. The expression should then be evaluated using 231 * be passed to it. The expression should then be evaluated using
173 * Dart_EvaluateExpr which will generate a closure that should be invoked 232 * Dart_EvaluateExpr which will generate a closure that should be invoked
174 * with the list of arguments passed to this method. 233 * with the list of arguments passed to this method.
175 * 234 *
176 * For example: 235 * For example:
177 * <code> 236 * <code>
178 * _consoleTempVariables = {'a' : someValue, 'b': someOtherValue} 237 * _consoleTempVariables = {'a' : someValue, 'b': someOtherValue}
179 * wrapExpressionAsClosure("${_CONSOLE_API_SUPPORT_HEADER35}foo + bar + a", 238 * wrapExpressionAsClosure("foo + bar + a", ["bar", 40, "foo", 2], true)
180 * ["bar", 40, "foo", 2])
181 * </code> 239 * </code>
182 * will return: 240 * will return:
183 * <code> 241 * <code>
184 * ["""(final $consoleVariables, final bar, final foo, final a, final b) => 242 * ["""(final $consoleVariables, final bar, final foo, final a, final b) =>
185 * (foo + bar + a 243 * (foo + bar + a
186 * )""", 244 * )""",
187 * [_consoleTempVariables, 40, 2, someValue, someOtherValue]] 245 * [_consoleTempVariables, 40, 2, someValue, someOtherValue]]
188 * </code> 246 * </code>
189 */ 247 */
190 static List wrapExpressionAsClosure(String expression, List locals) { 248 static List wrapExpressionAsClosure(String expression, List locals,
191 // FIXME: dartbug.com/10434 find a less fragile way to determine whether 249 bool includeCommandLineAPI) {
192 // we need to strip off console API support added by InjectedScript.
193 var args = {}; 250 var args = {};
194 var sb = new StringBuffer("("); 251 var sb = new StringBuffer("(");
195 addArg(arg, value) { 252 addArg(arg, value) {
196 arg = stripMemberName(arg); 253 arg = stripMemberName(arg);
197 if (args.containsKey(arg)) return; 254 if (args.containsKey(arg)) return;
198 // We ignore arguments with the name 'this' rather than throwing an 255 // We ignore arguments with the name 'this' rather than throwing an
199 // exception because Dart_GetLocalVariables includes 'this' and it 256 // exception because Dart_GetLocalVariables includes 'this' and it
200 // is more convenient to filter it out here than from C++ code. 257 // is more convenient to filter it out here than from C++ code.
201 // 'this' needs to be handled by calling Dart_EvaluateExpr with 258 // 'this' needs to be handled by calling Dart_EvaluateExpr with
202 // 'this' as the target rather than by passing it as an argument. 259 // 'this' as the target rather than by passing it as an argument.
203 if (arg == 'this') return; 260 if (arg == 'this') return;
204 if (args.isNotEmpty) { 261 if (args.isNotEmpty) {
205 sb.write(", "); 262 sb.write(", ");
206 } 263 }
207 sb.write("final $arg"); 264 sb.write("final $arg");
208 args[arg] = value; 265 args[arg] = value;
209 } 266 }
210 267
211 if (expectsConsoleApi(expression)) { 268 if (includeCommandLineAPI) {
212 expression = expression.substring(expression.indexOf('\n') + 1);
213 expression = expression.substring(0, expression.lastIndexOf('\n'));
214
215 addArg("\$consoleVariables", _consoleTempVariables); 269 addArg("\$consoleVariables", _consoleTempVariables);
216 270
217 // FIXME: use a real Dart tokenizer. The following regular expressions 271 // FIXME: use a real Dart tokenizer. The following regular expressions
218 // only allow setting variables at the immediate start of the expression 272 // only allow setting variables at the immediate start of the expression
219 // to limit the number of edge cases we have to handle. 273 // to limit the number of edge cases we have to handle.
220 274
221 // Match expressions that start with "var x" 275 // Match expressions that start with "var x"
222 final _VARIABLE_DECLARATION = new RegExp("^(\\s*)var\\s+(\\w+)"); 276 final _VARIABLE_DECLARATION = new RegExp("^(\\s*)var\\s+(\\w+)");
223 // Match expressions that start with "someExistingConsoleVar =" 277 // Match expressions that start with "someExistingConsoleVar ="
224 final _SET_VARIABLE = new RegExp("^(\\s*)(\\w+)(\\s*=)"); 278 final _SET_VARIABLE = new RegExp("^(\\s*)(\\w+)(\\s*=)");
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 315
262 // TODO(jacobr): remove the parentheses around the expresson once 316 // TODO(jacobr): remove the parentheses around the expresson once
263 // dartbug.com/13723 is fixed. Currently we wrap expression in parentheses 317 // dartbug.com/13723 is fixed. Currently we wrap expression in parentheses
264 // to ensure only valid Dart expressions are allowed. Otherwise the DartVM 318 // to ensure only valid Dart expressions are allowed. Otherwise the DartVM
265 // quietly ignores trailing Dart statements resulting in user confusion 319 // quietly ignores trailing Dart statements resulting in user confusion
266 // when part of an invalid expression they entered is ignored. 320 // when part of an invalid expression they entered is ignored.
267 sb..write(') => (\n$expression\n)'); 321 sb..write(') => (\n$expression\n)');
268 return [sb.toString(), args.values.toList(growable: false)]; 322 return [sb.toString(), args.values.toList(growable: false)];
269 } 323 }
270 324
271 /** 325 static String _getShortSymbolName(Symbol symbol,
272 * TODO(jacobr): this is a big hack to get around the fact that we are still 326 DeclarationMirror declaration) {
273 * passing some JS expression to the evaluate method even when in a Dart 327 var name = MirrorSystem.getName(symbol);
274 * context. 328 if (declaration is MethodMirror) {
275 */ 329 if (declaration.isSetter && name[name.length-1] == "=") {
276 static bool isJsExpression(String expression) => 330 return name.substring(0, name.length-1);
277 expression.startsWith("(function getCompletions"); 331 }
332 if (declaration.isConstructor) {
333 return name.substring(name.indexOf('.') + 1);
334 }
335 }
336 return name;
337 }
278 338
279 /** 339 /**
280 * Returns a list of completions to use if the receiver is o. 340 * Returns a list of completions to use if the receiver is o.
281 */ 341 */
282 static List<String> getCompletions(o) { 342 static List<String> getCompletions(o) {
283 MirrorSystem system = currentMirrorSystem(); 343 MirrorSystem system = currentMirrorSystem();
284 var completions = new Set<String>(); 344 var completions = new Set<String>();
285 addAll(Map<Symbol, dynamic> map, bool isStatic) { 345 addAll(Map<Symbol, dynamic> map, bool isStatic) {
286 map.forEach((symbol, mirror) { 346 map.forEach((symbol, mirror) {
287 if (mirror.isStatic == isStatic && !mirror.isPrivate) { 347 if (mirror.isStatic == isStatic && !mirror.isPrivate) {
(...skipping 18 matching lines...) Expand all
306 366
307 if (o is Type) { 367 if (o is Type) {
308 addForClass(reflectClass(o), true); 368 addForClass(reflectClass(o), true);
309 } else { 369 } else {
310 addForClass(reflect(o).type, false); 370 addForClass(reflect(o).type, false);
311 } 371 }
312 return completions.toList(growable: false); 372 return completions.toList(growable: false);
313 } 373 }
314 374
315 /** 375 /**
316 * Convenience helper to get the keys of a [Map] as a [List]. 376 * Adds all candidate String completitions from [declarations] to [output]
317 */ 377 * filtering based on [staticContext] and [includePrivate].
378 */
379 static void _getCompletionsHelper(ClassMirror classMirror,
380 bool staticContext, LibraryMirror libraryMirror, Set<String> output) {
381 bool includePrivate = libraryMirror == classMirror.owner;
382 classMirror.declarations.forEach((symbol, declaration) {
383 if (!includePrivate && declaration.isPrivate) return;
384 if (declaration is VariableMirror) {
385 if (staticContext != declaration.isStatic) return;
386 } else if (declaration is MethodMirror) {
387 if (declaration.isOperator) return;
388 if (declaration.isConstructor) {
389 if (!staticContext) return;
390 var name = MirrorSystem.getName(declaration.constructorName);
391 if (name.isNotEmpty) output.add(name);
392 return;
393 }
394 if (staticContext != declaration.isStatic) return;
395 } else if (declaration is TypeMirror) {
396 return;
397 }
398 output.add(_getShortSymbolName(symbol, declaration));
399 });
400
401 if (!staticContext) {
402 for (var interface in classMirror.superinterfaces) {
403 _getCompletionsHelper(interface, staticContext,
404 libraryMirror, output);
405 }
406 if (classMirror.superclass != null) {
407 _getCompletionsHelper(classMirror.superclass, staticContext,
408 libraryMirror, output);
409 }
410 }
411 }
412
413 static void _getLibraryCompletionsHelper(
414 LibraryMirror library, bool includePrivate, Set<String> output) {
415 library.declarations.forEach((symbol, declaration) {
416 if (!includePrivate && declaration.isPrivate) return;
417 output.add(_getShortSymbolName(symbol, declaration));
418 });
419 }
420
421 static LibraryMirror getLibraryMirror(String url) =>
422 currentMirrorSystem().libraries[Uri.parse(url)];
423
424 /**
425 * Get code completions for [o] only showing privates from [libraryUrl].
426 */
427 static List<String> getObjectCompletions(o, String libraryUrl) {
428 var classMirror;
429 bool staticContext;
430 if (o is Type) {
431 classMirror = reflectClass(o);
432 staticContext = true;
433 } else {
434 classMirror = reflect(o).type;
435 staticContext = false;
436 }
437 var names = new Set<String>();
438 getClassCompletions(classMirror, names, staticContext, libraryUrl);
439 return names.toList()..sort();
440 }
441
442 static void getClassCompletions(ClassMirror classMirror, Set<String> names,
443 bool staticContext, String libraryUrl) {
444 LibraryMirror libraryMirror = getLibraryMirror(libraryUrl);
445 _getCompletionsHelper(classMirror, staticContext, libraryMirror, names);
446 }
447
448 static List<String> getLibraryCompletions(String url) {
449 var names = new Set<String>();
450 _getLibraryCompletionsHelper(getLibraryMirror(url), true, names);
451 return names.toList();
452 }
453
454 /**
455 * Get valid code completitions from within a library and all libraries
456 * imported by that library.
457 */
458 static List<String> getLibraryCompletionsIncludingImports(String url) {
459 var names = new Set<String>();
460 var libraryMirror = getLibraryMirror(url);
461 _getLibraryCompletionsHelper(libraryMirror, true, names);
462 for (var dependency in libraryMirror.libraryDependencies) {
463 if (dependency.isImport) {
464 if (dependency.prefix == null) {
465 _getLibraryCompletionsHelper(dependency.targetLibrary, false, names);
466 } else {
467 names.add(MirrorSystem.getName(dependency.prefix));
468 }
469 }
470 }
471 return names.toList();
472 }
473
474 static final SIDE_EFFECT_FREE_LIBRARIES = new Set<String>()
475 ..add('dart:html')
476 ..add('dart:indexed_db')
477 ..add('dart:svg')
478 ..add('dart:typed_data')
479 ..add('dart:web_audio')
480 ..add('dart:web_gl')
481 ..add('dart:web_sql');
482
483 static LibraryMirror _getLibrary(MethodMirror methodMirror) {
484 var owner = methodMirror.owner;
485 if (owner is ClassMirror) {
486 return owner;
487 } else if (owner is LibraryMirror) {
488 return owner;
489 }
490 return null;
491 }
492
493 /**
494 * For parity with the JavaScript debugger, we treat some getters as if
495 * they are fields so that users can see their values immediately.
496 * This matches JavaScript's behavior for getters on DOM objects.
497 * In the future we should consider adding an annotation to tag getters
498 * in user libraries as side effect free.
499 */
500 static bool _isSideEffectFreeGetter(MethodMirror methodMirror,
501 LibraryMirror libraryMirror) {
502 // This matches JavaScript behavior. We should consider displaying
503 // getters for all dart platform libraries rather than just the DOM
504 // libraries.
505 return libraryMirror.uri.scheme == 'dart' &&
506 SIDE_EFFECT_FREE_LIBRARIES.contains(libraryMirror.uri.toString());
507 }
508
509 /**
510 * Whether we should treat a property as a field for the purposes of the
511 * debugger.
512 */
513 static bool treatPropertyAsField(MethodMirror methodMirror,
514 LibraryMirror libraryMirror) {
515 return (methodMirror.isGetter || methodMirror.isSetter) &&
516 (methodMirror.isSynthetic ||
517 _isSideEffectFreeGetter(methodMirror,libraryMirror));
518 }
519
520 // TODO(jacobr): generate more concise function descriptions instead of
521 // dumping the entire function source.
522 static String describeFunction(function) {
523 if (function is _Trampoline) return function._methodMirror.source;
524 try {
525 return reflect(function).function.source;
526 } catch (e) {
527 return function.toString();
528 }
529 }
530
531 static List getInvocationTrampolineDetails(_Trampoline method) {
532 var loc = method._methodMirror.location;
533 return [loc.line, loc.column, loc.sourceUri.toString(),
534 MirrorSystem.getName(method._selector)];
535 }
536
537 static List getLibraryProperties(String libraryUrl, bool ownProperties,
538 bool accessorPropertiesOnly) {
539 var properties = new Map<String, _Property>();
540 var libraryMirror = getLibraryMirror(libraryUrl);
541 _addInstanceMirrors(libraryMirror, libraryMirror,
542 libraryMirror.declarations,
543 ownProperties, accessorPropertiesOnly, false, false,
544 properties);
545 if (!accessorPropertiesOnly) {
546 // We need to add class properties for all classes in the library.
547 libraryMirror.declarations.forEach((symbol, declarationMirror) {
548 if (declarationMirror is ClassMirror) {
549 var name = MirrorSystem.getName(symbol);
550 if (declarationMirror.hasReflectedType
551 && !properties.containsKey(name)) {
552 properties[name] = new _Property(name)
553 ..value = declarationMirror.reflectedType;
554 }
555 }
556 });
557 }
558 return packageProperties(properties);
559 }
560
561 static List getObjectProperties(o, bool ownProperties,
562 bool accessorPropertiesOnly) {
563 var properties = new Map<String, _Property>();
564 var names = new Set<String>();
565 var objectMirror = reflect(o);
566 var classMirror = objectMirror.type;
567 _addInstanceMirrors(objectMirror, classMirror.owner,
568 classMirror.instanceMembers,
569 ownProperties, accessorPropertiesOnly, false, true,
570 properties);
571 return packageProperties(properties);
572 }
573
574 static List getObjectClassProperties(o, bool ownProperties,
575 bool accessorPropertiesOnly) {
576 var properties = new Map<String, _Property>();
577 var objectMirror = reflect(o);
578 var classMirror = objectMirror.type;
579 _addInstanceMirrors(objectMirror, classMirror.owner,
580 classMirror.instanceMembers,
581 ownProperties, accessorPropertiesOnly, true, false,
582 properties);
583 _addStatics(classMirror, properties, accessorPropertiesOnly);
584 return packageProperties(properties);
585 }
586
587 static List getClassProperties(Type t, bool ownProperties,
588 bool accessorPropertiesOnly) {
589 var properties = new Map<String, _Property>();
590 var classMirror = reflectClass(t);
591 _addStatics(classMirror, properties, accessorPropertiesOnly);
592 return packageProperties(properties);
593 }
594
595 static void _addStatics(ClassMirror classMirror,
596 Map<String, _Property> properties,
597 bool accessorPropertiesOnly) {
598 var libraryMirror = classMirror.owner;
599 classMirror.declarations.forEach((symbol, declaration) {
600 var name = _getShortSymbolName(symbol, declaration);
601 if (declaration is VariableMirror) {
602 if (accessorPropertiesOnly) return;
603 if (!declaration.isStatic) return;
604 properties.putIfAbsent(name, () => new _Property(name))
605 ..value = classMirror.getField(symbol).reflectee
606 ..writable = !declaration.isFinal && !declaration.isConst;
607 } else if (declaration is MethodMirror) {
608 MethodMirror methodMirror = declaration;
609 // FIXMEDART: should we display constructors?
610 if (methodMirror.isConstructor) return;
611 if (!methodMirror.isStatic) return;
612 if (accessorPropertiesOnly) {
613 if (methodMirror.isRegularMethod ||
614 treatPropertyAsField(methodMirror, libraryMirror)) {
615 return;
616 }
617 } else if (!methodMirror.isRegularMethod &&
618 !treatPropertyAsField(methodMirror, libraryMirror)) {
619 return;
620 }
621 var property = properties.putIfAbsent(name, () => new _Property(name));
622 _fillMethodMirrorProperty(libraryMirror, classMirror, methodMirror,
623 symbol, accessorPropertiesOnly, property);
624 }
625 });
626 }
627
628 static void _fillMethodMirrorProperty(LibraryMirror libraryMirror,
629 Mirror methodOwner, MethodMirror methodMirror, Symbol symbol,
630 bool accessorPropertiesOnly, _Property property) {
631 if (methodMirror.isRegularMethod) {
632 property
633 ..value = new _MethodTrampoline(methodOwner, methodMirror, symbol)
634 ..isMethod = true;
635 } else if (methodMirror.isGetter) {
636 if (treatPropertyAsField(methodMirror, libraryMirror)) {
637 try {
638 property.value = methodOwner.getField(symbol).reflectee;
639 } catch (e) {
640 property
641 ..wasThrown = true
642 ..value = e;
643 }
644 } else if (accessorPropertiesOnly) {
645 property.getter = new _GetterTrampoline(methodOwner,
646 methodMirror, symbol);
647 }
648 } else if (methodMirror.isSetter) {
649 if (accessorPropertiesOnly &&
650 !treatPropertyAsField(methodMirror, libraryMirror)) {
651 property.setter = new _SetterTrampoline(methodOwner,
652 methodMirror, MirrorSystem.getSymbol(property.name, libraryMirror));
653 }
654 property.writable = true;
655 }
656 }
657
658 /**
659 * Helper method that handles collecting up properties from classes
660 * or libraries using the filters [ownProperties], [accessorPropertiesOnly],
661 * [hideFields], and [hideMethods] to determine which properties are
662 * collected. [accessorPropertiesOnly] specifies whether all properties
663 * should be returned or just accessors. [hideFields] specifies whether
664 * fields should be hidden. hideMethods specifies whether methods should be
665 * shown or hidden. [ownProperties] is not currently used but is part of the
666 * Blink devtools API for enumerating properties.
667 */
668 static void _addInstanceMirrors(
669 ObjectMirror objectMirror,
670 LibraryMirror libraryMirror,
671 Map<Symbol, Mirror> declarations,
672 bool ownProperties, bool accessorPropertiesOnly,
673 bool hideFields, bool hideMethods,
674 Map<String, _Property> properties) {
675 declarations.forEach((Symbol symbol, Mirror declaration) {
676 if (declaration is TypedefMirror || declaration is ClassMirror) return;
677 var name = _getShortSymbolName(symbol, declaration);
678 bool isField = declaration is VariableMirror ||
679 (declaration is MethodMirror &&
680 treatPropertyAsField(declaration, libraryMirror));
681 if ((isField && hideFields) || (hideMethods && !isField)) return;
682 if (accessorPropertiesOnly) {
683 if (declaration is VariableMirror || declaration.isRegularMethod ||
684 isField) {
685 return;
686 }
687 } else if (declaration is MethodMirror &&
688 (declaration.isGetter || declaration.isSetter) &&
689 !treatPropertyAsField(declaration, libraryMirror)) {
690 return;
691 }
692 var property = properties.putIfAbsent(name, () => new _Property(name));
693 if (declaration is VariableMirror) {
694 property
695 ..value = objectMirror.getField(symbol).reflectee
696 ..writable = !declaration.isFinal && !declaration.isConst;
697 return;
698 }
699 _fillMethodMirrorProperty(libraryMirror, objectMirror, declaration,
700 symbol, accessorPropertiesOnly, property);
701 });
702 }
703
704 /**
705 * Flatten down the properties data structure into a List that is easy to
706 * access from native code.
707 */
708 static List packageProperties(Map<String, _Property> properties) {
709 var ret = [];
710 for (var property in properties.values) {
711 ret.addAll([property.name,
712 property.setter,
713 property.getter,
714 property.value,
715 property.hasValue,
716 property.writable,
717 property.isMethod,
718 property.isOwn,
719 property.wasThrown]);
720 }
721 return ret;
722 }
723
724 /**
725 * Get a property, returning null if the property does not exist.
726 * For private property names, we attempt to resolve the property in the
727 * context of each library that the property name could be associated with.
728 */
729 static getObjectPropertySafe(o, String propertyName) {
730 var objectMirror = reflect(o);
731 var classMirror = objectMirror.type;
732 if (propertyName.startsWith("_")) {
733 var attemptedLibraries = new Set<LibraryMirror>();
734 while (classMirror != null) {
735 LibraryMirror library = classMirror.owner;
736 if (!attemptedLibraries.contains(library)) {
737 try {
738 return objectMirror.getField(
739 MirrorSystem.getSymbol(propertyName, library)).reflectee;
740 } catch (e) { }
741 attemptedLibraries.add(library);
742 }
743 classMirror = classMirror.superclass;
744 }
745 return null;
746 }
747 try {
748 return objectMirror.getField(
749 MirrorSystem.getSymbol(propertyName)).reflectee;
750 } catch (e) {
751 return null;
752 }
753 }
754
755 /**
756 * Helper to wrap the inspect method on InjectedScriptHost to provide the
757 * inspect method required for the
758 */
759 static List consoleApi(host) {
760 return [
761 "inspect",
762 (o) {
763 host.inspect(o, null);
764 return o;
765 },
766 "dir",
767 window().console.dir,
768 "dirxml",
769 window().console.dirxml
770 // FIXME: add copy method.
771 ];
772 }
773
318 static List getMapKeyList(Map map) => map.keys.toList(); 774 static List getMapKeyList(Map map) => map.keys.toList();
319 775
320 /**
321 * Returns the keys of an arbitrary Dart Map encoded as unique Strings.
322 * Keys that are strings are left unchanged except that the prefix ":" is
323 * added to disambiguate keys from other Dart members.
324 * Keys that are not strings have # followed by the index of the key in the ma p
325 * prepended to disambuguate. This scheme is simplistic but easy to encode and
326 * decode. The use case for this method is displaying all map keys in a human
327 * readable way in debugging tools.
328 */
329 static List<String> getEncodedMapKeyList(dynamic obj) {
330 if (obj is! Map) return null;
331
332 var ret = new List<String>();
333 int i = 0;
334 return obj.keys.map((key) {
335 var encodedKey;
336 if (key is String) {
337 encodedKey = ':$key';
338 } else {
339 // If the key isn't a string, return a guaranteed unique for this map
340 // string representation of the key that is still somewhat human
341 // readable.
342 encodedKey = '#${i}:$key';
343 }
344 i++;
345 return encodedKey;
346 }).toList(growable: false);
347 }
348
349 static final RegExp _NON_STRING_KEY_REGEXP = new RegExp("^#(\\d+):(.+)\$");
350
351 static _decodeKey(Map map, String key) {
352 // The key is a regular old String.
353 if (key.startsWith(':')) return key.substring(1);
354
355 var match = _NON_STRING_KEY_REGEXP.firstMatch(key);
356 if (match != null) {
357 int index = int.parse(match.group(1));
358 var iter = map.keys.skip(index);
359 if (iter.isNotEmpty) {
360 var ret = iter.first;
361 // Validate that the toString representation of the key matches what we
362 // expect. FIXME: throw an error if it does not.
363 assert(match.group(2) == '$ret');
364 return ret;
365 }
366 }
367 return null;
368 }
369
370 /**
371 * Converts keys encoded with [getEncodedMapKeyList] to their actual keys.
372 */
373 static lookupValueForEncodedMapKey(Map obj, String key) => obj[_decodeKey(obj, key)];
374
375 /**
376 * Builds a constructor name with the form expected by the C Dart mirrors API.
377 */
378 static String buildConstructorName(String className, String constructorName) = > '$className.$constructorName';
379
380 /**
381 * Strips the class name from an expression of the form "className.someName".
382 */
383 static String stripClassName(String str, String className) {
384 if (str.length > className.length + 1 &&
385 str.startsWith(className) && str[className.length] == '.') {
386 return str.substring(className.length + 1);
387 } else {
388 return str;
389 }
390 }
391
392 /**
393 * Removes the trailing dot from an expression ending in a dot.
394 * This method is used as Library prefixes include a trailing dot when using
395 * the C Dart debugger API.
396 */
397 static String stripTrailingDot(String str) =>
398 (str != null && str[str.length - 1] == '.') ? str.substring(0, str.length - 1) : str;
399
400 static String addTrailingDot(String str) => '${str}.';
401
402 static String demangle(String str) {
403 var atPos = str.indexOf('@');
404 return atPos == -1 ? str : str.substring(0, atPos);
405 }
406
407 static bool isNoSuchMethodError(obj) => obj is NoSuchMethodError; 776 static bool isNoSuchMethodError(obj) => obj is NoSuchMethodError;
408 777
409 static void register(Document document, String tag, Type type, 778 static void register(Document document, String tag, Type type,
410 String extendsTagName) { 779 String extendsTagName) {
411 var nativeClass = _validateCustomType(type); 780 var nativeClass = _validateCustomType(type);
412 781
413 if (extendsTagName == null) { 782 if (extendsTagName == null) {
414 if (nativeClass.reflectedType != HtmlElement) { 783 if (nativeClass.reflectedType != HtmlElement) {
415 throw new UnsupportedError('Class must provide extendsTag if base ' 784 throw new UnsupportedError('Class must provide extendsTag if base '
416 'native class is not HTMLElement'); 785 'native class is not HTMLElement');
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 _scheduleImmediateHelper._schedule(callback); 978 _scheduleImmediateHelper._schedule(callback);
610 }; 979 };
611 980
612 get _pureIsolateScheduleImmediateClosure => ((void callback()) => 981 get _pureIsolateScheduleImmediateClosure => ((void callback()) =>
613 throw new UnimplementedError("scheduleMicrotask in background isolates " 982 throw new UnimplementedError("scheduleMicrotask in background isolates "
614 "are not supported in the browser")); 983 "are not supported in the browser"));
615 984
616 void _initializeCustomElement(Element e) { 985 void _initializeCustomElement(Element e) {
617 _Utils.initializeCustomElement(e); 986 _Utils.initializeCustomElement(e);
618 } 987 }
OLDNEW
« no previous file with comments | « tools/dom/idl/dart/dart.idl ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698