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

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

Issue 2100803007: Array formatting customized to look like JS (Closed) Base URL: https://github.com/dart-lang/dev_compiler.git@master
Patch Set: submit Created 4 years, 5 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
« no previous file with comments | « lib/runtime/dart_sdk.js ('k') | tool/sdk_expected_errors.txt » ('j') | 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) 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';
11 import 'dart:html' as html; 11 import 'dart:html' as html;
12 import 'dart:math';
12 13
13 /// JsonMLConfig object to pass to devtools to specify how an Object should 14 /// JsonMLConfig object to pass to devtools to specify how an Object should
14 /// be displayed. skipDart signals that an object should not be formatted 15 /// be displayed. skipDart signals that an object should not be formatted
15 /// by the Dart formatter. This is used to specify that an Object 16 /// by the Dart formatter. This is used to specify that an Object
16 /// should just be displayed using the regular JavaScript view instead of a 17 /// should just be displayed using the regular JavaScript view instead of a
17 /// custom Dart view. For example, this is used to display the JavaScript view 18 /// custom Dart view. For example, this is used to display the JavaScript view
18 /// of a Dart Function as a child of the regular Function object. keyToString 19 /// of a Dart Function as a child of the regular Function object. keyToString
19 /// signals that a map key object should have its toString() displayed by 20 /// signals that a map key object should have its toString() displayed by
20 /// the Dart formatter. 21 /// the Dart formatter.
21 /// 22 ///
22 /// We'd like this to be an enum, but we can't because it's a dev_compiler bug. 23 /// We'd like this to be an enum, but we can't because it's a dev_compiler bug.
23 class JsonMLConfig { 24 class JsonMLConfig {
24 const JsonMLConfig(this.name); 25 const JsonMLConfig(this.name);
25 26
26 final String name; 27 final String name;
27 static const none = const JsonMLConfig("none"); 28 static const none = const JsonMLConfig("none");
28 static const skipDart = const JsonMLConfig("skipDart"); 29 static const skipDart = const JsonMLConfig("skipDart");
29 static const keyToString = const JsonMLConfig("keyToString"); 30 static const keyToString = const JsonMLConfig("keyToString");
30 } 31 }
31 32
32 final int maxIterableChildrenToDisplay = 50; 33 int maxSpanLength = 100;
33 34
34 var _devtoolsFormatter = new JsonMLFormatter(new DartFormatter()); 35 var _devtoolsFormatter = new JsonMLFormatter(new DartFormatter());
35 36
36 String _typeof(object) => JS('String', 'typeof #', object); 37 String _typeof(object) => JS('String', 'typeof #', object);
37 38
38 List<String> getOwnPropertyNames(object) => JS('List<String>', 39 List<String> getOwnPropertyNames(object) => JS('List<String>',
39 'dart.list(Object.getOwnPropertyNames(#), #)', object, String); 40 'dart.list(Object.getOwnPropertyNames(#), #)', object, String);
40 41
41 List getOwnPropertySymbols(object) => 42 List getOwnPropertySymbols(object) =>
42 JS('List', 'Object.getOwnPropertySymbols(#)', object); 43 JS('List', 'Object.getOwnPropertySymbols(#)', object);
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 bool hasMethod(object, String name) { 92 bool hasMethod(object, String name) {
92 try { 93 try {
93 return dart.hasMethod(object, name); 94 return dart.hasMethod(object, name);
94 } catch (e) { 95 } catch (e) {
95 return false; 96 return false;
96 } 97 }
97 } 98 }
98 99
99 /// [JsonMLFormatter] consumes [NameValuePair] objects and 100 /// [JsonMLFormatter] consumes [NameValuePair] objects and
100 class NameValuePair { 101 class NameValuePair {
101 NameValuePair({this.name, this.value, this.config: JsonMLConfig.none}); 102 NameValuePair(
103 {this.name,
104 this.value,
105 this.config: JsonMLConfig.none,
106 this.hideName: false});
102 107
103 // Define equality and hashCode so that NameValuePair can be used 108 // Define equality and hashCode so that NameValuePair can be used
104 // in a Set to dedupe entries with duplicate names. 109 // in a Set to dedupe entries with duplicate names.
105 operator ==(other) => other is NameValuePair && other.name == name; 110 operator ==(other) => other is NameValuePair && other.name == name;
106 int get hashCode => name.hashCode; 111 int get hashCode => name.hashCode;
107 112
108 final String name; 113 final String name;
109 final Object value; 114 final Object value;
110 final JsonMLConfig config; 115 final JsonMLConfig config;
116 final bool hideName;
117
118 String get displayName => hideName ? '' : name;
111 } 119 }
112 120
113 class MapEntry { 121 class MapEntry {
114 MapEntry({this.key, this.value}); 122 MapEntry({this.key, this.value});
115 123
116 final Object key; 124 final Object key;
117 final Object value; 125 final Object value;
118 } 126 }
119 127
128 class IterableSpan {
129 IterableSpan({this.start, this.end, this.iterable});
130
131 final int start;
132 final int end;
133 final Iterable iterable;
134 }
135
120 class ClassMetadata { 136 class ClassMetadata {
121 ClassMetadata(this.object); 137 ClassMetadata(this.object);
122 138
123 final Object object; 139 final Object object;
124 } 140 }
125 141
126 class HeritageClause { 142 class HeritageClause {
127 HeritageClause(this.name, this.types); 143 HeritageClause(this.name, this.types);
128 144
129 final String name; 145 final String name;
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 var body = new JsonMLElement('ol') 247 var body = new JsonMLElement('ol')
232 ..setStyle('list-style-type: none;' 248 ..setStyle('list-style-type: none;'
233 'padding-left: 0px;' 249 'padding-left: 0px;'
234 'margin-top: 0px;' 250 'margin-top: 0px;'
235 'margin-bottom: 0px;' 251 'margin-bottom: 0px;'
236 'margin-left: 12px'); 252 'margin-left: 12px');
237 var children = _simpleFormatter.children(object); 253 var children = _simpleFormatter.children(object);
238 for (NameValuePair child in children) { 254 for (NameValuePair child in children) {
239 var li = body.createChild('li'); 255 var li = body.createChild('li');
240 var nameSpan = new JsonMLElement('span') 256 var nameSpan = new JsonMLElement('span')
241 ..createTextChild(child.name != null ? child.name + ': ' : '') 257 ..createTextChild(
258 child.displayName.isNotEmpty ? '${child.displayName}: ' : '')
242 ..setStyle('color: rgb(136, 19, 145);'); 259 ..setStyle('color: rgb(136, 19, 145);');
243 if (_typeof(child.value) == 'object' || 260 if (_typeof(child.value) == 'object' ||
244 _typeof(child.value) == 'function') { 261 _typeof(child.value) == 'function') {
245 nameSpan.addStyle("padding-left: 13px;"); 262 nameSpan.addStyle("padding-left: 13px;");
246 263
247 li.appendChild(nameSpan); 264 li.appendChild(nameSpan);
248 var objectTag = li.createObjectTag(child.value); 265 var objectTag = li.createObjectTag(child.value);
249 objectTag.addAttribute('config', child.config); 266 objectTag.addAttribute('config', child.config);
250 if (!_simpleFormatter.hasChildren(child.value)) { 267 if (!_simpleFormatter.hasChildren(child.value)) {
251 li.setStyle("padding-left: 13px;"); 268 li.setStyle("padding-left: 13px;");
(...skipping 20 matching lines...) Expand all
272 List<Formatter> _formatters; 289 List<Formatter> _formatters;
273 290
274 DartFormatter() { 291 DartFormatter() {
275 // The order of formatters matters as formatters later in the list take 292 // The order of formatters matters as formatters later in the list take
276 // precidence. 293 // precidence.
277 _formatters = [ 294 _formatters = [
278 new FunctionFormatter(), 295 new FunctionFormatter(),
279 new MapFormatter(), 296 new MapFormatter(),
280 new IterableFormatter(), 297 new IterableFormatter(),
281 new MapEntryFormatter(), 298 new MapEntryFormatter(),
299 new IterableSpanFormatter(),
282 new ClassMetadataFormatter(), 300 new ClassMetadataFormatter(),
283 new HeritageClauseFormatter(), 301 new HeritageClauseFormatter(),
284 new ObjectFormatter() 302 new ObjectFormatter(),
285 ]; 303 ];
286 } 304 }
287 305
288 String preview(object) { 306 String preview(object) {
289 try { 307 try {
290 if (object == null || 308 if (object == null ||
291 object is num || 309 object is num ||
292 object is String || 310 object is String ||
293 isNativeJavaScriptObject(object)) { 311 isNativeJavaScriptObject(object)) {
294 return object.toString(); 312 return object.toString();
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
487 } 505 }
488 } 506 }
489 507
490 bool hasChildren(object) => true; 508 bool hasChildren(object) => true;
491 509
492 List<NameValuePair> children(object) { 510 List<NameValuePair> children(object) {
493 // TODO(jacobr): be lazier about enumerating contents of Iterables that 511 // TODO(jacobr): be lazier about enumerating contents of Iterables that
494 // are not the built in Set or List types. 512 // are not the built in Set or List types.
495 // TODO(jacobr): handle large Iterables better. 513 // TODO(jacobr): handle large Iterables better.
496 // TODO(jacobr): consider only using numeric indices 514 // TODO(jacobr): consider only using numeric indices
497 Iterable iterable = object;
498 var ret = new LinkedHashSet<NameValuePair>(); 515 var ret = new LinkedHashSet<NameValuePair>();
499 var i = 0; 516 ret.addAll(childrenHelper(
500 for (var entry in iterable) { 517 new IterableSpan(start: 0, end: object.length, iterable: object)));
501 if (i > maxIterableChildrenToDisplay) {
502 ret.add(new NameValuePair(
503 name: 'Warning', value: 'Truncated Iterable display'));
504 // TODO(jacobr): provide an expandable entry to show more entries.
505 break;
506 }
507 ret.add(new NameValuePair(name: i.toString(), value: entry));
508 i++;
509 }
510 // TODO(jacobr): provide a link to show regular class properties here. 518 // TODO(jacobr): provide a link to show regular class properties here.
511 // required for subclasses of iterable, etc. 519 // required for subclasses of iterable, etc.
512 addMetadataChildren(object, ret); 520 addMetadataChildren(object, ret);
513 return ret.toList(); 521 return ret.toList();
514 } 522 }
515 } 523 }
516 524
517 // This class does double duting displaying metadata for 525 // This class does double duting displaying metadata for
518 class ClassMetadataFormatter implements Formatter { 526 class ClassMetadataFormatter implements Formatter {
519 accept(object) => object is ClassMetadata; 527 accept(object) => object is ClassMetadata;
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 List<NameValuePair> children(object) { 608 List<NameValuePair> children(object) {
601 HeritageClause clause = object; 609 HeritageClause clause = object;
602 var ret = <NameValuePair>[]; 610 var ret = <NameValuePair>[];
603 for (var type in clause.types) { 611 for (var type in clause.types) {
604 ret.add(new NameValuePair(value: new ClassMetadata(type))); 612 ret.add(new NameValuePair(value: new ClassMetadata(type)));
605 } 613 }
606 return ret; 614 return ret;
607 } 615 }
608 } 616 }
609 617
618 /// Formatter for synthetic IterableSpan objects used to display contents of
619 /// an Iterable cleanly.
620 class IterableSpanFormatter implements Formatter {
621 accept(object) => object is IterableSpan;
622
623 String preview(object) {
624 IterableSpan entry = object;
625 return '[${object.start}...${object.end-1}]';
626 }
627
628 bool hasChildren(object) => true;
629
630 List<NameValuePair> children(object) => childrenHelper(object);
631 }
632
633 List<NameValuePair> childrenHelper(IterableSpan span) {
634 var length = span.end - span.start;
635 var ret = new List<NameValuePair>();
636 if (length <= maxSpanLength) {
637 for (var i = span.start; i < span.end; i++) {
638 /// TODO(bmilligan): Stop using elementAt if it becomes a performance
639 /// bottleneck in the future.
640 ret.add(new NameValuePair(
641 name: i.toString(), value: span.iterable.elementAt(i)));
642 }
643 } else {
644 /// Using length - .5, a list of length 10000 results in a
645 /// maxPowerOfSubsetSize of 1, so the list will be broken up into 100,
646 /// 100-length subsets. A list of length 10001 results in a
647 /// maxPowerOfSubsetSize of 2, so the list will be broken up into 1
648 /// 10000-length subset and 1 1-length subset.
649 var maxPowerOfSubsetSize =
650 (log(length - .5) / log(maxSpanLength)).truncate();
651 var subsetSize = pow(maxSpanLength, maxPowerOfSubsetSize);
652 for (var i = span.start; i < span.end; i += subsetSize) {
653 var endIndex = min(span.end, subsetSize + i);
654 if (endIndex - i == 1)
655 ret.add(new NameValuePair(
656 name: i.toString(), value: span.iterable.elementAt(i)));
657 else {
658 var entryWrapper =
659 new IterableSpan(start: i, end: endIndex, iterable: span.iterable);
660 ret.add(new NameValuePair(
661 name: '[${i}...${endIndex - 1}]',
662 value: entryWrapper,
663 hideName: true));
664 }
665 }
666 }
667 return ret;
668 }
669
610 /// This entry point is automatically invoked by the code generated by 670 /// This entry point is automatically invoked by the code generated by
611 /// Dart Dev Compiler 671 /// Dart Dev Compiler
612 registerDevtoolsFormatter() { 672 registerDevtoolsFormatter() {
613 var formatters = [_devtoolsFormatter]; 673 var formatters = [_devtoolsFormatter];
614 JS('', 'dart.global.devtoolsFormatters = #', formatters); 674 JS('', 'dart.global.devtoolsFormatters = #', formatters);
615 } 675 }
OLDNEW
« no previous file with comments | « lib/runtime/dart_sdk.js ('k') | tool/sdk_expected_errors.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698