OLD | NEW |
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 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 } | 119 } |
120 | 120 |
121 class MapEntry { | 121 class MapEntry { |
122 MapEntry({this.key, this.value}); | 122 MapEntry({this.key, this.value}); |
123 | 123 |
124 final Object key; | 124 final Object key; |
125 final Object value; | 125 final Object value; |
126 } | 126 } |
127 | 127 |
128 class IterableSpan { | 128 class IterableSpan { |
129 IterableSpan({this.start, this.end, this.iterable}); | 129 IterableSpan(this.start, this.end, this.iterable); |
130 | 130 |
131 final int start; | 131 final int start; |
132 final int end; | 132 final int end; |
133 final Iterable iterable; | 133 final Iterable iterable; |
| 134 int get length => end - start; |
| 135 |
| 136 /// Using length - .5, a list of length 10000 results in a |
| 137 /// maxPowerOfSubsetSize of 1, so the list will be broken up into 100, |
| 138 /// 100-length subsets. A list of length 10001 results in a |
| 139 /// maxPowerOfSubsetSize of 2, so the list will be broken up into 1 |
| 140 /// 10000-length subset and 1 1-length subset. |
| 141 int get maxPowerOfSubsetSize => |
| 142 (log(length - .5) / log(_maxSpanLength)).truncate(); |
| 143 int get subsetSize => pow(_maxSpanLength, maxPowerOfSubsetSize); |
| 144 |
| 145 Map<int, dynamic> asMap() => |
| 146 iterable.skip(start).take(length).toList().asMap(); |
| 147 |
| 148 List<NameValuePair> children() { |
| 149 var ret = <NameValuePair>[]; |
| 150 if (length <= _maxSpanLength) { |
| 151 asMap().forEach((i, element) { |
| 152 ret.add( |
| 153 new NameValuePair(name: (i + start).toString(), value: element)); |
| 154 }); |
| 155 } else { |
| 156 for (var i = start; i < end; i += subsetSize) { |
| 157 var subSpan = new IterableSpan(i, min(end, subsetSize + i), iterable); |
| 158 if (subSpan.length == 1) { |
| 159 ret.add(new NameValuePair( |
| 160 name: i.toString(), value: iterable.elementAt(i))); |
| 161 } else { |
| 162 ret.add(new NameValuePair( |
| 163 name: '[${i}...${subSpan.end - 1}]', |
| 164 value: subSpan, |
| 165 hideName: true)); |
| 166 } |
| 167 } |
| 168 } |
| 169 return ret; |
| 170 } |
134 } | 171 } |
135 | 172 |
136 class ClassMetadata { | 173 class ClassMetadata { |
137 ClassMetadata(this.object); | 174 ClassMetadata(this.object); |
138 | 175 |
139 final Object object; | 176 final Object object; |
140 } | 177 } |
141 | 178 |
142 class HeritageClause { | 179 class HeritageClause { |
143 HeritageClause(this.name, this.types); | 180 HeritageClause(this.name, this.types); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 /// This class renders the simple structured format objects [_simpleFormatter] | 248 /// This class renders the simple structured format objects [_simpleFormatter] |
212 /// provides as JsonML. | 249 /// provides as JsonML. |
213 class JsonMLFormatter { | 250 class JsonMLFormatter { |
214 // TODO(jacobr): define a SimpleFormatter base class that DartFormatter | 251 // TODO(jacobr): define a SimpleFormatter base class that DartFormatter |
215 // implements if we decide to use this class elsewhere. We specify that the | 252 // implements if we decide to use this class elsewhere. We specify that the |
216 // type is DartFormatter here purely to get type checking benefits not because | 253 // type is DartFormatter here purely to get type checking benefits not because |
217 // this class is really intended to only support instances of type | 254 // this class is really intended to only support instances of type |
218 // DartFormatter. | 255 // DartFormatter. |
219 DartFormatter _simpleFormatter; | 256 DartFormatter _simpleFormatter; |
220 | 257 |
| 258 bool customFormattersOn = false; |
| 259 |
221 JsonMLFormatter(this._simpleFormatter); | 260 JsonMLFormatter(this._simpleFormatter); |
222 | 261 |
223 void setMaxSpanLengthForTestingOnly(int spanLength) { | 262 void setMaxSpanLengthForTestingOnly(int spanLength) { |
224 _maxSpanLength = spanLength; | 263 _maxSpanLength = spanLength; |
225 } | 264 } |
226 | 265 |
227 header(object, config) { | 266 header(object, config) { |
| 267 customFormattersOn = true; |
228 if (config == JsonMLConfig.skipDart || isNativeJavaScriptObject(object)) { | 268 if (config == JsonMLConfig.skipDart || isNativeJavaScriptObject(object)) { |
229 return null; | 269 return null; |
230 } | 270 } |
231 | 271 |
232 var c = _simpleFormatter.preview(object); | 272 var c = _simpleFormatter.preview(object); |
233 if (c == null) return null; | 273 if (c == null) return null; |
234 | 274 |
235 if (config == JsonMLConfig.keyToString) { | 275 if (config == JsonMLConfig.keyToString) { |
236 c = object.toString(); | 276 c = object.toString(); |
237 } | 277 } |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 } | 550 } |
511 | 551 |
512 bool hasChildren(object) => true; | 552 bool hasChildren(object) => true; |
513 | 553 |
514 List<NameValuePair> children(object) { | 554 List<NameValuePair> children(object) { |
515 // TODO(jacobr): be lazier about enumerating contents of Iterables that | 555 // TODO(jacobr): be lazier about enumerating contents of Iterables that |
516 // are not the built in Set or List types. | 556 // are not the built in Set or List types. |
517 // TODO(jacobr): handle large Iterables better. | 557 // TODO(jacobr): handle large Iterables better. |
518 // TODO(jacobr): consider only using numeric indices | 558 // TODO(jacobr): consider only using numeric indices |
519 var ret = new LinkedHashSet<NameValuePair>(); | 559 var ret = new LinkedHashSet<NameValuePair>(); |
520 ret.addAll(childrenHelper( | 560 ret.addAll((new IterableSpan(0, object.length, object)).children()); |
521 new IterableSpan(start: 0, end: object.length, iterable: object))); | |
522 // TODO(jacobr): provide a link to show regular class properties here. | 561 // TODO(jacobr): provide a link to show regular class properties here. |
523 // required for subclasses of iterable, etc. | 562 // required for subclasses of iterable, etc. |
524 addMetadataChildren(object, ret); | 563 addMetadataChildren(object, ret); |
525 return ret.toList(); | 564 return ret.toList(); |
526 } | 565 } |
527 } | 566 } |
528 | 567 |
529 // This class does double duting displaying metadata for | 568 // This class does double duting displaying metadata for |
530 class ClassMetadataFormatter implements Formatter { | 569 class ClassMetadataFormatter implements Formatter { |
531 accept(object) => object is ClassMetadata; | 570 accept(object) => object is ClassMetadata; |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
618 return ret; | 657 return ret; |
619 } | 658 } |
620 } | 659 } |
621 | 660 |
622 /// Formatter for synthetic IterableSpan objects used to display contents of | 661 /// Formatter for synthetic IterableSpan objects used to display contents of |
623 /// an Iterable cleanly. | 662 /// an Iterable cleanly. |
624 class IterableSpanFormatter implements Formatter { | 663 class IterableSpanFormatter implements Formatter { |
625 accept(object) => object is IterableSpan; | 664 accept(object) => object is IterableSpan; |
626 | 665 |
627 String preview(object) { | 666 String preview(object) { |
628 IterableSpan entry = object; | |
629 return '[${object.start}...${object.end-1}]'; | 667 return '[${object.start}...${object.end-1}]'; |
630 } | 668 } |
631 | 669 |
632 bool hasChildren(object) => true; | 670 bool hasChildren(object) => true; |
633 | 671 |
634 List<NameValuePair> children(object) => childrenHelper(object); | 672 List<NameValuePair> children(object) => object.children(); |
635 } | |
636 | |
637 List<NameValuePair> childrenHelper(IterableSpan span) { | |
638 var length = span.end - span.start; | |
639 var ret = new List<NameValuePair>(); | |
640 if (length <= _maxSpanLength) { | |
641 for (var i = span.start; i < span.end; i++) { | |
642 /// TODO(bmilligan): Stop using elementAt if it becomes a performance | |
643 /// bottleneck in the future. | |
644 ret.add(new NameValuePair( | |
645 name: i.toString(), value: span.iterable.elementAt(i))); | |
646 } | |
647 } else { | |
648 /// Using length - .5, a list of length 10000 results in a | |
649 /// maxPowerOfSubsetSize of 1, so the list will be broken up into 100, | |
650 /// 100-length subsets. A list of length 10001 results in a | |
651 /// maxPowerOfSubsetSize of 2, so the list will be broken up into 1 | |
652 /// 10000-length subset and 1 1-length subset. | |
653 var maxPowerOfSubsetSize = | |
654 (log(length - .5) / log(_maxSpanLength)).truncate(); | |
655 var subsetSize = pow(_maxSpanLength, maxPowerOfSubsetSize); | |
656 for (var i = span.start; i < span.end; i += subsetSize) { | |
657 var endIndex = min(span.end, subsetSize + i); | |
658 if (endIndex - i == 1) | |
659 ret.add(new NameValuePair( | |
660 name: i.toString(), value: span.iterable.elementAt(i))); | |
661 else { | |
662 var entryWrapper = | |
663 new IterableSpan(start: i, end: endIndex, iterable: span.iterable); | |
664 ret.add(new NameValuePair( | |
665 name: '[${i}...${endIndex - 1}]', | |
666 value: entryWrapper, | |
667 hideName: true)); | |
668 } | |
669 } | |
670 } | |
671 return ret; | |
672 } | 673 } |
673 | 674 |
674 /// This entry point is automatically invoked by the code generated by | 675 /// This entry point is automatically invoked by the code generated by |
675 /// Dart Dev Compiler | 676 /// Dart Dev Compiler |
676 registerDevtoolsFormatter() { | 677 registerDevtoolsFormatter() { |
677 var formatters = [_devtoolsFormatter]; | 678 var formatters = [_devtoolsFormatter]; |
678 JS('', 'dart.global.devtoolsFormatters = #', formatters); | 679 JS('', 'dart.global.devtoolsFormatters = #', formatters); |
679 } | 680 } |
OLD | NEW |