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

Side by Side Diff: pkg/dev_compiler/tool/input_sdk/private/debugger.dart

Issue 2703263002: Custom formatter cleanup Fix case where displaying a class constructor generated unreadable huge ou… (Closed)
Patch Set: Custom formatter cleanup Fix case where displaying a class constructor generated unreadable huge ou… Created 3 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
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 library dart._debugger; 5 library dart._debugger;
6 6
7 import 'dart:_foreign_helper' show JS; 7 import 'dart:_foreign_helper' show JS;
8 import 'dart:_runtime' as dart; 8 import 'dart:_runtime' as dart;
9 import 'dart:core'; 9 import 'dart:core';
10 import 'dart:collection'; 10 import 'dart:collection';
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 class JSNative { 46 class JSNative {
47 // Name may be a String or a Symbol. 47 // Name may be a String or a Symbol.
48 static getProperty(object, name) => JS('', '#[#]', object, name); 48 static getProperty(object, name) => JS('', '#[#]', object, name);
49 // Name may be a String or a Symbol. 49 // Name may be a String or a Symbol.
50 static setProperty(object, name, value) => 50 static setProperty(object, name, value) =>
51 JS('', '#[#]=#', object, name, value); 51 JS('', '#[#]=#', object, name, value);
52 } 52 }
53 53
54 void addMetadataChildren(object, Set<NameValuePair> ret) { 54 void addMetadataChildren(object, Set<NameValuePair> ret) {
55 ret.add(new NameValuePair( 55 ret.add(new NameValuePair(
56 name: getTypeName(_getType(object)), 56 name: "[[class]]",
57 value: object, 57 value: dart.getReifiedType(object),
58 config: JsonMLConfig.asClass)); 58 config: JsonMLConfig.asClass));
59 } 59 }
60 60
61 /// Add properties from a signature definition [sig] for [object].
62 /// Walk the prototype chain if [walkProtypeChain] is set.
63 /// Tag types on function typed properties of [object] if [tagTypes] is set.
64 ///
65 void addPropertiesFromSignature(
66 sig, Set<NameValuePair> properties, object, bool walkPrototypeChain,
67 {tagTypes: false}) {
68 // Including these property names doesn't add any value and just clutters
69 // the debugger output.
70 // TODO(jacobr): consider adding runtimeType to this list.
71 var skippedNames = new Set()..add('hashCode');
72
73 while (sig != null) {
74 for (var symbol in getOwnPropertySymbols(sig)) {
75 var dartName = symbolName(symbol);
76 String dartXPrefix = 'dartx.';
77 if (dartName.startsWith(dartXPrefix)) {
78 dartName = dartName.substring(dartXPrefix.length);
79 }
80 if (skippedNames.contains(dartName)) continue;
81 var value = safeGetProperty(object, symbol);
82 // Tag the function with its runtime type.
83 if (tagTypes && _typeof(value) == 'function') {
84 dart.tag(value, JS('', '#[#]', sig, symbol));
85 }
86 properties.add(new NameValuePair(name: dartName, value: value));
87 }
88
89 for (var name in getOwnPropertyNames(sig)) {
90 var value = safeGetProperty(object, name);
91 if (skippedNames.contains(name)) continue;
92 // Tag the function with its runtime type.
93 if (tagTypes && _typeof(value) == 'function') {
94 dart.tag(value, JS('', '#[#]', sig, name));
95 }
96 properties.add(new NameValuePair(name: name, value: value));
97 }
98
99 if (!walkPrototypeChain) break;
100
101 sig = safeGetProperty(sig, '__proto__');
102 }
103 }
104
105 /// Sort properties sorting public names before private names.
106 List<NameValuePair> sortProperties(Iterable<NameValuePair> properties) {
107 var sortedProperties = properties.toList();
108
109 sortedProperties.sort((a, b) {
110 var aPrivate = a.name.startsWith('_');
111 var bPrivate = b.name.startsWith('_');
112 if (aPrivate != bPrivate) return aPrivate ? 1 : -1;
113 return a.name.compareTo(b.name);
114 });
115 return sortedProperties;
116 }
117
61 String getObjectTypeName(object) { 118 String getObjectTypeName(object) {
62 var reifiedType = dart.getReifiedType(object); 119 var reifiedType = dart.getReifiedType(object);
63 if (reifiedType == null) { 120 if (reifiedType == null) {
64 if (_typeof(object) == 'function') { 121 if (_typeof(object) == 'function') {
65 return '[[Raw JavaScript Function]]'; 122 return '[[Raw JavaScript Function]]';
66 } 123 }
67 return '<Error getting type name>'; 124 return '<Error getting type name>';
68 } 125 }
69 return getTypeName(reifiedType); 126 return getTypeName(reifiedType);
70 } 127 }
71 128
72 String getTypeName(Type type) { 129 String getTypeName(type) {
73 var name = dart.typeName(type); 130 var name = dart.typeName(type);
74 // Hack to cleanup names for List<dynamic> 131 // Hack to cleanup names for List<dynamic>
75 // TODO(jacobr): it would be nice if there was a way we could distinguish 132 // TODO(jacobr): it would be nice if there was a way we could distinguish
76 // between a List<dynamic> created from Dart and an Array passed in from 133 // between a List<dynamic> created from Dart and an Array passed in from
77 // JavaScript. 134 // JavaScript.
78 if (name == 'JSArray<dynamic>' || name == 'JSObject<Array>') 135 if (name == 'JSArray<dynamic>' || name == 'JSObject<Array>')
79 return 'List<dynamic>'; 136 return 'List<dynamic>';
80 return name; 137 return name;
81 } 138 }
82 139
83 Object _getType(object) =>
84 object is Type ? object : dart.getReifiedType(object);
85
86 String safePreview(object, config) { 140 String safePreview(object, config) {
87 try { 141 try {
88 var preview = _devtoolsFormatter._simpleFormatter.preview(object, config); 142 var preview = _devtoolsFormatter._simpleFormatter.preview(object, config);
89 if (preview != null) return preview; 143 if (preview != null) return preview;
90 return object.toString(); 144 return object.toString();
91 } catch (e) { 145 } catch (e) {
92 return '<Exception thrown> $e'; 146 return '<Exception thrown> $e';
93 } 147 }
94 } 148 }
95 149
(...skipping 14 matching lines...) Expand all
110 /// [JsonMLFormatter] consumes [NameValuePair] objects and 164 /// [JsonMLFormatter] consumes [NameValuePair] objects and
111 class NameValuePair { 165 class NameValuePair {
112 NameValuePair( 166 NameValuePair(
113 {this.name, 167 {this.name,
114 this.value, 168 this.value,
115 this.config: JsonMLConfig.none, 169 this.config: JsonMLConfig.none,
116 this.hideName: false}); 170 this.hideName: false});
117 171
118 // Define equality and hashCode so that NameValuePair can be used 172 // Define equality and hashCode so that NameValuePair can be used
119 // in a Set to dedupe entries with duplicate names. 173 // in a Set to dedupe entries with duplicate names.
120 operator ==(other) => other is NameValuePair && other.name == name; 174 bool operator ==(other) {
175 if (other is! NameValuePair) return false;
176 if (this.hideName || other.hideName) return identical(this, other);
177 return other.name == name;
178 }
179
121 int get hashCode => name.hashCode; 180 int get hashCode => name.hashCode;
122 181
123 final String name; 182 final String name;
124 final Object value; 183 final Object value;
125 final JsonMLConfig config; 184 final JsonMLConfig config;
126 final bool hideName; 185 final bool hideName;
127 186
128 String get displayName => hideName ? '' : name; 187 String get displayName => hideName ? '' : name;
129 } 188 }
130 189
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 } 321 }
263 322
264 /// Whether an object is a native JavaScript type where we should display the 323 /// Whether an object is a native JavaScript type where we should display the
265 /// JavaScript view of the object instead of the custom Dart specific render 324 /// JavaScript view of the object instead of the custom Dart specific render
266 /// of properties. 325 /// of properties.
267 bool isNativeJavaScriptObject(object) { 326 bool isNativeJavaScriptObject(object) {
268 var type = _typeof(object); 327 var type = _typeof(object);
269 // Treat Node objects as a native JavaScript type as the regular DOM render 328 // Treat Node objects as a native JavaScript type as the regular DOM render
270 // in devtools is superior to the dart specific view. 329 // in devtools is superior to the dart specific view.
271 return (type != 'object' && type != 'function') || 330 return (type != 'object' && type != 'function') ||
272 object is dart.JSObject || 331 dart.isJsInterop(object) ||
273 object is html.Node; 332 object is html.Node;
274 } 333 }
275 334
276 /// Class implementing the Devtools Formatter API described by: 335 /// Class implementing the Devtools Formatter API described by:
277 /// https://docs.google.com/document/d/1FTascZXT9cxfetuPRT2eXPQKXui4nWFivUnS_335 T3U 336 /// https://docs.google.com/document/d/1FTascZXT9cxfetuPRT2eXPQKXui4nWFivUnS_335 T3U
278 /// Specifically, a formatter implements a header, hasBody, and body method. 337 /// Specifically, a formatter implements a header, hasBody, and body method.
279 /// This class renders the simple structured format objects [_simpleFormatter] 338 /// This class renders the simple structured format objects [_simpleFormatter]
280 /// provides as JsonML. 339 /// provides as JsonML.
281 class JsonMLFormatter { 340 class JsonMLFormatter {
282 // TODO(jacobr): define a SimpleFormatter base class that DartFormatter 341 // TODO(jacobr): define a SimpleFormatter base class that DartFormatter
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 var body = new JsonMLElement('ol') 380 var body = new JsonMLElement('ol')
322 ..setStyle('list-style-type: none;' 381 ..setStyle('list-style-type: none;'
323 'padding-left: 0px;' 382 'padding-left: 0px;'
324 'margin-top: 0px;' 383 'margin-top: 0px;'
325 'margin-bottom: 0px;' 384 'margin-bottom: 0px;'
326 'margin-left: 12px;'); 385 'margin-left: 12px;');
327 if (object is StackTrace) { 386 if (object is StackTrace) {
328 body.addStyle('color: rgb(196, 26, 22);'); 387 body.addStyle('color: rgb(196, 26, 22);');
329 } 388 }
330 var children = _simpleFormatter.children(object, config); 389 var children = _simpleFormatter.children(object, config);
390 if (children == null) return body.toJsonML();
331 for (NameValuePair child in children) { 391 for (NameValuePair child in children) {
332 var li = body.createChild('li'); 392 var li = body.createChild('li');
333 var nameSpan = new JsonMLElement('span') 393 li.setStyle("padding-left: 13px;");
334 ..createTextChild( 394
335 child.displayName.isNotEmpty ? '${child.displayName}: ' : '') 395 // The value is indented when it is on a different line from the name
336 ..setStyle('color: rgb(136, 19, 145);'); 396 // by setting right padding of the name to -13px and the padding of the
397 // value to 13px.
398 JsonMLElement nameSpan;
399 var valueStyle = '';
400 if (!child.hideName) {
401 nameSpan = new JsonMLElement('span')
402 ..createTextChild(
403 child.displayName.isNotEmpty ? '${child.displayName}: ' : '')
404 ..setStyle('color: rgb(136, 19, 145); margin-right: -13px');
405 valueStyle = 'margin-left: 13px';
406 }
407
337 if (_typeof(child.value) == 'object' || 408 if (_typeof(child.value) == 'object' ||
338 _typeof(child.value) == 'function') { 409 _typeof(child.value) == 'function') {
339 nameSpan.addStyle("padding-left: 13px;"); 410 var valueSpan = new JsonMLElement('span')..setStyle(valueStyle);
340 411 valueSpan.createObjectTag(child.value)
341 li.appendChild(nameSpan); 412 ..addAttribute('config', child.config);
342 var objectTag = li.createObjectTag(child.value); 413 if (nameSpan != null) {
343 objectTag.addAttribute('config', child.config); 414 li.appendChild(nameSpan);
344 if (!_simpleFormatter.hasChildren(child.value, child.config)) {
345 li.setStyle("padding-left: 13px;");
346 } 415 }
416 li.appendChild(valueSpan);
347 } else { 417 } else {
348 li.setStyle("padding-left: 13px;"); 418 var line = li.createChild('span');
349 li.createChild('span') 419 if (nameSpan != null) {
350 ..appendChild(nameSpan) 420 line.appendChild(nameSpan);
351 ..createTextChild(safePreview(child.value, child.config)); 421 }
422 line.appendChild(new JsonMLElement('span')
423 ..createTextChild(safePreview(child.value, child.config))
424 ..setStyle(valueStyle));
352 } 425 }
353 } 426 }
354 return body.toJsonML(); 427 return body.toJsonML();
355 } 428 }
356 } 429 }
357 430
358 abstract class Formatter { 431 abstract class Formatter {
359 bool accept(object, config); 432 bool accept(object, config);
360 String preview(object); 433 String preview(object);
361 bool hasChildren(object); 434 bool hasChildren(object);
362 List<NameValuePair> children(object); 435 List<NameValuePair> children(object);
363 } 436 }
364 437
365 class DartFormatter { 438 class DartFormatter {
366 List<Formatter> _formatters; 439 List<Formatter> _formatters;
367 440
368 DartFormatter() { 441 DartFormatter() {
369 // The order of formatters matters as formatters earlier in the list take 442 // The order of formatters matters as formatters earlier in the list take
370 // precedence. 443 // precedence.
371 _formatters = [ 444 _formatters = [
372 new ClassFormatter(), 445 new ClassFormatter(),
446 new TypeFormatter(),
373 new NamedConstructorFormatter(), 447 new NamedConstructorFormatter(),
374 new MapFormatter(), 448 new MapFormatter(),
375 new IterableFormatter(), 449 new IterableFormatter(),
376 new IterableSpanFormatter(), 450 new IterableSpanFormatter(),
377 new MapEntryFormatter(), 451 new MapEntryFormatter(),
378 new StackTraceFormatter(), 452 new StackTraceFormatter(),
379 new FunctionFormatter(), 453 new FunctionFormatter(),
380 new HeritageClauseFormatter(), 454 new HeritageClauseFormatter(),
381 new LibraryModuleFormatter(), 455 new LibraryModuleFormatter(),
382 new LibraryFormatter(), 456 new LibraryFormatter(),
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
430 } catch (e, trace) { 504 } catch (e, trace) {
431 // See comment for preview. 505 // See comment for preview.
432 html.window.console.error("Caught exception $e\n trace:\n$trace"); 506 html.window.console.error("Caught exception $e\n trace:\n$trace");
433 } 507 }
434 return <NameValuePair>[]; 508 return <NameValuePair>[];
435 } 509 }
436 } 510 }
437 511
438 /// Default formatter for Dart Objects. 512 /// Default formatter for Dart Objects.
439 class ObjectFormatter extends Formatter { 513 class ObjectFormatter extends Formatter {
440 static Set<String> _customNames = new Set()
441 ..add('constructor')
442 ..add('prototype')
443 ..add('__proto__');
444 bool accept(object, config) => !isNativeJavaScriptObject(object); 514 bool accept(object, config) => !isNativeJavaScriptObject(object);
445 515
446 String preview(object) => getObjectTypeName(object); 516 String preview(object) => getObjectTypeName(object);
447 517
448 bool hasChildren(object) => true; 518 bool hasChildren(object) => true;
449 519
450 List<NameValuePair> children(object) { 520 List<NameValuePair> children(object) {
451 var properties = new LinkedHashSet<NameValuePair>(); 521 var type = dart.getType(object);
452 // Set of property names used to avoid duplicates. 522 var ret = new LinkedHashSet<NameValuePair>();
453 addMetadataChildren(object, properties); 523 // We use a Set rather than a List to avoid duplicates.
454 524 var properties = new Set<NameValuePair>();
455 var current = object; 525 addPropertiesFromSignature(
456 526 dart.getFieldSig(type), properties, object, true);
457 var protoChain = <Object>[]; 527 addPropertiesFromSignature(
458 while (current != null && 528 dart.getGetterSig(type), properties, object, true);
459 !isNativeJavaScriptObject(current) && 529 ret.addAll(sortProperties(properties));
460 JS("bool", "# !== Object.prototype", current)) { 530 addMetadataChildren(object, ret);
461 protoChain.add(current); 531 return ret.toList();
462 current = safeGetProperty(current, '__proto__');
463 }
464
465 // We walk the prototype chain for symbol properties because they take
466 // priority and are accessed instead of Dart properties according to Dart
467 // calling conventions.
468 // TODO(jacobr): where possible use the data stored by dart.setSignature
469 // instead of walking the JavaScript object directly.
470 for (current in protoChain) {
471 for (var symbol in getOwnPropertySymbols(current)) {
472 var dartName = symbolName(symbol);
473 if (hasMethod(object, dartName)) {
474 continue;
475 }
476 // TODO(jacobr): find a cleaner solution than checking for dartx
477 String dartXPrefix = 'dartx.';
478 if (dartName.startsWith(dartXPrefix)) {
479 dartName = dartName.substring(dartXPrefix.length);
480 } else if (!dartName.startsWith('_')) {
481 // Dart method extension names should either be from dartx or should
482 // start with an _
483 continue;
484 }
485 var value = safeGetProperty(object, symbol);
486 properties.add(new NameValuePair(name: dartName, value: value));
487 }
488 }
489
490 for (current in protoChain) {
491 // TODO(jacobr): optionally distinguish properties and fields so that
492 // it is safe to expand untrusted objects without side effects.
493 var className = dart.getReifiedType(current).name;
494 for (var name in getOwnPropertyNames(current)) {
495 if (_customNames.contains(name) || name == className) continue;
496 if (hasMethod(object, name)) {
497 continue;
498 }
499 var value = safeGetProperty(object, name);
500 properties.add(new NameValuePair(name: name, value: value));
501 }
502 }
503
504 return properties.toList();
505 } 532 }
506 } 533 }
507 534
508 /// Formatter for module Dart Library objects. 535 /// Formatter for module Dart Library objects.
509 class LibraryModuleFormatter implements Formatter { 536 class LibraryModuleFormatter implements Formatter {
510 accept(object, config) => dart.getDartLibraryName(object) != null; 537 accept(object, config) => dart.getModuleName(object) != null;
511 538
512 bool hasChildren(object) => true; 539 bool hasChildren(object) => true;
513 540
514 String preview(object) { 541 String preview(object) {
515 var libraryNames = dart.getDartLibraryName(object).split('/'); 542 var libraryNames = dart.getModuleName(object).split('/');
516 // Library names are received with a repeat directory name, so strip the 543 // Library names are received with a repeat directory name, so strip the
517 // last directory entry here to make the path cleaner. For example, the 544 // last directory entry here to make the path cleaner. For example, the
518 // library "third_party/dart/utf/utf" shoud display as 545 // library "third_party/dart/utf/utf" shoud display as
519 // "third_party/dart/utf/". 546 // "third_party/dart/utf/".
520 if (libraryNames.length > 1) { 547 if (libraryNames.length > 1 &&
548 libraryNames.last == libraryNames[libraryNames.length - 2]) {
521 libraryNames[libraryNames.length - 1] = ''; 549 libraryNames[libraryNames.length - 1] = '';
522 } 550 }
523 return 'Library Module: ${libraryNames.join('/')}'; 551 return 'Library Module: ${libraryNames.join('/')}';
524 } 552 }
525 553
526 List<NameValuePair> children(object) { 554 List<NameValuePair> children(object) {
527 var children = new LinkedHashSet<NameValuePair>(); 555 var children = new LinkedHashSet<NameValuePair>();
528 for (var name in getOwnPropertyNames(object)) { 556 for (var name in getOwnPropertyNames(object)) {
529 var value = safeGetProperty(object, name); 557 var value = safeGetProperty(object, name);
530 // Replace __ with / to make file paths more readable. Then
531 // 'src__result__error' becomes 'src/result/error'.
532 name = '${name.replaceAll("__", "/")}.dart';
533 children.add(new NameValuePair( 558 children.add(new NameValuePair(
534 name: name, value: new Library(name, value), hideName: true)); 559 name: name, value: new Library(name, value), hideName: true));
535 } 560 }
536 return children.toList(); 561 return children.toList();
537 } 562 }
538 } 563 }
539 564
540 class LibraryFormatter implements Formatter { 565 class LibraryFormatter implements Formatter {
541 var genericParameters = new HashMap<String, String>(); 566 var genericParameters = new HashMap<String, String>();
542 567
543 accept(object, config) => object is Library; 568 accept(object, config) => object is Library;
544 569
545 bool hasChildren(object) => true; 570 bool hasChildren(object) => true;
546 571
547 String preview(object) => object.name; 572 String preview(object) => object.name;
548 573
549 List<NameValuePair> children(object) { 574 List<NameValuePair> children(object) {
575 // Maintain library member order rather than sorting members as is the
576 // case for class members.
550 var children = new LinkedHashSet<NameValuePair>(); 577 var children = new LinkedHashSet<NameValuePair>();
551 var nonGenericProperties = new LinkedHashMap<String, Object>();
552 var objectProperties = safeProperties(object.object); 578 var objectProperties = safeProperties(object.object);
553 objectProperties.forEach((name, value) { 579 objectProperties.forEach((name, value) {
554 var genericTypeConstructor = dart.getGenericTypeCtor(value); 580 // Skip the generic constructors for each class as users are only
555 if (genericTypeConstructor != null) { 581 // interested in seeing the actual classes.
556 recordGenericParameters(name, genericTypeConstructor); 582 if (dart.getGenericTypeCtor(value) != null) return;
557 } else { 583
558 nonGenericProperties[name] = value; 584 children.add(dart.isType(value)
559 } 585 ? classChild(name, value)
560 }); 586 : new NameValuePair(name: name, value: value));
561 nonGenericProperties.forEach((name, value) {
562 if (value is Type) {
563 children.add(classChild(name, value));
564 } else {
565 children.add(new NameValuePair(name: name, value: value));
566 }
567 }); 587 });
568 return children.toList(); 588 return children.toList();
569 } 589 }
570 590
571 recordGenericParameters(String name, Object genericTypeConstructor) {
572 // Using JS toString() eliminates the leading metadata that is generated
573 // with the toString function provided in operations.dart.
574 // Splitting by => and taking the first element gives the list of
575 // arguments in the constructor.
576 genericParameters[name] =
577 JS('String', '#.toString()', genericTypeConstructor)
578 .split(' =>')
579 .first
580 .replaceAll(new RegExp(r'[(|)]'), '');
581 }
582
583 classChild(String name, Object child) { 591 classChild(String name, Object child) {
584 var typeName = getTypeName(child); 592 var typeName = getTypeName(child);
585 // Generic class names are generated with a $ at the end, so the 593 return new NameValuePair(
586 // corresponding non-generic class can be identified by adding $. 594 name: typeName, value: child, config: JsonMLConfig.asClass);
587 var parameterName = '$name\$';
588 if (genericParameters.keys.contains(parameterName)) {
589 typeName = '$typeName<${genericParameters[parameterName]}>';
590 // TODO(bmilligan): Add a symbol to classes with generic types at their
591 // creation so they can be recognized independently by the debugger.
592 JSNative.setProperty(child, 'genericTypeName', typeName);
593 }
594 return new NameValuePair(name: typeName, value: child);
595 } 595 }
596 } 596 }
597 597
598 /// Formatter for Dart Function objects. 598 /// Formatter for Dart Function objects.
599 /// Dart functions happen to be regular JavaScript Function objects but 599 /// Dart functions happen to be regular JavaScript Function objects but
600 /// we can distinguish them based on whether they have been tagged with 600 /// we can distinguish them based on whether they have been tagged with
601 /// runtime type information. 601 /// runtime type information.
602 class FunctionFormatter implements Formatter { 602 class FunctionFormatter implements Formatter {
603 accept(object, config) { 603 accept(object, config) {
604 if (_typeof(object) != 'function') return false; 604 if (_typeof(object) != 'function') return false;
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
763 List<NameValuePair> children(object) => object 763 List<NameValuePair> children(object) => object
764 .toString() 764 .toString()
765 .split('\n') 765 .split('\n')
766 .map((line) => new NameValuePair( 766 .map((line) => new NameValuePair(
767 value: line.replaceFirst(new RegExp(r'^\s+at\s'), ''), 767 value: line.replaceFirst(new RegExp(r'^\s+at\s'), ''),
768 hideName: true)) 768 hideName: true))
769 .toList(); 769 .toList();
770 } 770 }
771 771
772 class ClassFormatter implements Formatter { 772 class ClassFormatter implements Formatter {
773 accept(object, config) => object is Type || config == JsonMLConfig.asClass; 773 accept(object, config) => config == JsonMLConfig.asClass;
774 774
775 String preview(object) { 775 String preview(type) {
776 var typeName = safeGetProperty(object, 'genericTypeName');
777 if (typeName != null) return typeName;
778 var type = _getType(object);
779 var implements = dart.getImplements(type); 776 var implements = dart.getImplements(type);
780 typeName = getTypeName(type); 777 var typeName = getTypeName(type);
781 if (implements != null) { 778 if (implements != null) {
782 var typeNames = implements().map(getTypeName); 779 var typeNames = implements().map(getTypeName);
783 return '${typeName} implements ${typeNames.join(", ")}'; 780 return '${typeName} implements ${typeNames.join(", ")}';
784 } else { 781 } else {
785 return typeName; 782 return typeName;
786 } 783 }
787 } 784 }
788 785
789 bool hasChildren(object) => true; 786 bool hasChildren(object) => true;
790 787
791 List<NameValuePair> children(object) { 788 List<NameValuePair> children(type) {
792 // TODO(jacobr): add other entries describing the class such as 789 // TODO(jacobr): add other entries describing the class such as
793 // links to the superclass, mixins, implemented interfaces, and methods. 790 // implemented interfaces, and methods.
794 var type = _getType(object); 791 var ret = new LinkedHashSet<NameValuePair>();
795 var children = <NameValuePair>[]; 792
796 var typeName = getTypeName(_getType(object)); 793 var staticProperties = new Set<NameValuePair>();
794 var staticMethods = new Set<NameValuePair>();
795 // Static fields and properties.
796 addPropertiesFromSignature(
797 dart.getStaticFieldSig(type), staticProperties, type, false);
798 addPropertiesFromSignature(
799 dart.getStaticGetterSig(type), staticProperties, type, false);
800 // static methods.
801 addPropertiesFromSignature(
802 dart.getStaticSig(type), staticMethods, type, false);
803
804 if (staticProperties.isNotEmpty || staticMethods.isNotEmpty) {
805 ret
806 ..add(new NameValuePair(value: '[[Static members]]', hideName: true))
807 ..addAll(sortProperties(staticProperties))
808 ..addAll(sortProperties(staticMethods));
809 }
810
811 // instance methods.
812 var instanceMethods = new Set<NameValuePair>();
813 // Instance methods are defined on the prototype not the constructor object.
814 addPropertiesFromSignature(dart.getMethodSig(type), instanceMethods,
815 JS('', '#.prototype', type), false,
816 tagTypes: true);
817 if (instanceMethods.isNotEmpty) {
818 ret
819 ..add(new NameValuePair(value: '[[Instance Methods]]', hideName: true))
820 ..addAll(sortProperties(instanceMethods));
821 }
822
823 var typeName = getTypeName(type);
797 var mixins = dart.getMixins(type); 824 var mixins = dart.getMixins(type);
798 if (mixins != null && mixins.isNotEmpty) { 825 if (mixins != null && mixins.isNotEmpty) {
799 children.add(new NameValuePair( 826 ret.add(new NameValuePair(
800 name: '[[Mixins]]', value: new HeritageClause('mixins', mixins))); 827 name: '[[Mixins]]', value: new HeritageClause('mixins', mixins)));
801 } 828 }
802 829
803 var hiddenProperties = ['length', 'name', 'prototype', 'genericTypeName']; 830 var baseProto = JS('', '#.__proto__', type);
804 // Addition of NameValuePairs for static variables and named constructors. 831 if (baseProto != null && !dart.isJsInterop(baseProto)) {
805 for (var name in getOwnPropertyNames(object)) { 832 ret.add(new NameValuePair(
806 // TODO(bmilligan): Perform more principled checks to filter out spurious 833 name: "[[base class]]",
807 // members. 834 value: baseProto,
808 if (hiddenProperties.contains(name)) continue; 835 config: JsonMLConfig.asClass));
809 var value = safeGetProperty(object, name);
810 if (value != null && dart.getIsNamedConstructor(value) != null) {
811 value = new NamedConstructor(value);
812 name = '${typeName}.$name';
813 }
814 children.add(new NameValuePair(name: name, value: value));
815 } 836 }
816 837
817 // TODO(bmilligan): Replace the hard coding of $identityHash. 838 // TODO(jacobr): add back fields for named constructors.
818 var hiddenPrototypeProperties = ['constructor', 'new', r'$identityHash']; 839 return ret.toList();
819 // Addition of class methods.
820 var prototype = JS('var', '#["prototype"]', object);
821 if (prototype != null) {
822 for (var name in getOwnPropertyNames(prototype)) {
823 if (hiddenPrototypeProperties.contains(name)) continue;
824 // Simulate dart.bind by using dart.tag and tear off the function
825 // so it will be recognized by the FunctionFormatter.
826 var function = safeGetProperty(prototype, name);
827 var constructor = safeGetProperty(prototype, 'constructor');
828 var sigObj = dart.getMethodSig(constructor);
829 if (sigObj != null) {
830 var value = safeGetProperty(sigObj, name);
831 if (getTypeName(dart.getReifiedType(value)) != 'Null') {
832 dart.tag(function, value);
833 children.add(new NameValuePair(name: name, value: function));
834 }
835 }
836 }
837 }
838 return children;
839 } 840 }
840 } 841 }
841 842
843 class TypeFormatter implements Formatter {
844 accept(object, config) => object is Type;
845
846 String preview(object) => object.toString();
847
848 bool hasChildren(object) => false;
849
850 List<NameValuePair> children(object) => [];
851 }
852
842 /// This entry point is automatically invoked by the code generated by 853 /// This entry point is automatically invoked by the code generated by
843 /// Dart Dev Compiler 854 /// Dart Dev Compiler
844 registerDevtoolsFormatter() { 855 registerDevtoolsFormatter() {
845 var formatters = [_devtoolsFormatter]; 856 var formatters = [_devtoolsFormatter];
846 JS('', 'dart.global.devtoolsFormatters = #', formatters); 857 JS('', 'dart.global.devtoolsFormatters = #', formatters);
847 } 858 }
859
860 // Expose these methods here to facilitate writing debugger tests.
861 // If export worked for private SDK libraries we could just export
862 // these methods from dart:_runtime.
863
864 getModuleNames() {
865 return dart.getModuleNames();
866 }
867
868 getModuleLibraries(String name) {
869 return dart.getModuleLibraries(name);
870 }
OLDNEW
« no previous file with comments | « pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/types.dart ('k') | pkg/dev_compiler/tool/input_sdk/private/js_helper.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698