| 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 |