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

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

Issue 2164763005: Library custom formatters (Closed) Base URL: https://github.com/dart-lang/dev_compiler.git@master
Patch Set: 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
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 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
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();
Jacob 2016/07/21 02:10:31 nice!
bmilligan 2016/07/22 18:25:18 Acknowledged.
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 }
171 }
172
173 class Library {
Jacob 2016/07/21 02:10:32 do you need to wrap the libraries? I would expect
bmilligan 2016/07/22 18:25:18 The symbol for the libraries is on the library mod
Jacob 2016/07/22 19:17:50 Acknowledged.
174 Library(this.name, this.object);
175
176 final String name;
177 final Object object;
178 }
179
180 class NamedConstructor {
181 NamedConstructor(this.object);
182
183 final Object object;
134 } 184 }
135 185
136 class ClassMetadata { 186 class ClassMetadata {
137 ClassMetadata(this.object); 187 ClassMetadata(this.object);
138 188
139 final Object object; 189 final Object object;
190 String get name =>
191 getTypeName(object is Type ? object : dart.getReifiedType(object));
140 } 192 }
141 193
142 class HeritageClause { 194 class HeritageClause {
143 HeritageClause(this.name, this.types); 195 HeritageClause(this.name, this.types);
144 196
145 final String name; 197 final String name;
146 final List types; 198 final List types;
147 } 199 }
148 200
149 /// Class to simplify building the JsonML objects expected by the 201 /// Class to simplify building the JsonML objects expected by the
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 /// This class renders the simple structured format objects [_simpleFormatter] 263 /// This class renders the simple structured format objects [_simpleFormatter]
212 /// provides as JsonML. 264 /// provides as JsonML.
213 class JsonMLFormatter { 265 class JsonMLFormatter {
214 // TODO(jacobr): define a SimpleFormatter base class that DartFormatter 266 // TODO(jacobr): define a SimpleFormatter base class that DartFormatter
215 // implements if we decide to use this class elsewhere. We specify that the 267 // 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 268 // type is DartFormatter here purely to get type checking benefits not because
217 // this class is really intended to only support instances of type 269 // this class is really intended to only support instances of type
218 // DartFormatter. 270 // DartFormatter.
219 DartFormatter _simpleFormatter; 271 DartFormatter _simpleFormatter;
220 272
273 bool customFormattersOn = false;
274
221 JsonMLFormatter(this._simpleFormatter); 275 JsonMLFormatter(this._simpleFormatter);
222 276
223 void setMaxSpanLengthForTestingOnly(int spanLength) { 277 void setMaxSpanLengthForTestingOnly(int spanLength) {
224 _maxSpanLength = spanLength; 278 _maxSpanLength = spanLength;
225 } 279 }
226 280
227 header(object, config) { 281 header(object, config) {
282 customFormattersOn = true;
228 if (config == JsonMLConfig.skipDart || isNativeJavaScriptObject(object)) { 283 if (config == JsonMLConfig.skipDart || isNativeJavaScriptObject(object)) {
229 return null; 284 return null;
230 } 285 }
231 286
232 var c = _simpleFormatter.preview(object); 287 var c = _simpleFormatter.preview(object);
233 if (c == null) return null; 288 if (c == null) return null;
234 289
235 if (config == JsonMLConfig.keyToString) { 290 if (config == JsonMLConfig.keyToString) {
236 c = object.toString(); 291 c = object.toString();
237 } 292 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
286 bool accept(object); 341 bool accept(object);
287 String preview(object); 342 String preview(object);
288 bool hasChildren(object); 343 bool hasChildren(object);
289 List<NameValuePair> children(object); 344 List<NameValuePair> children(object);
290 } 345 }
291 346
292 class DartFormatter { 347 class DartFormatter {
293 List<Formatter> _formatters; 348 List<Formatter> _formatters;
294 349
295 DartFormatter() { 350 DartFormatter() {
296 // The order of formatters matters as formatters later in the list take 351 // The order of formatters matters as formatters earlier in the list take
297 // precidence. 352 // precedence.
Jacob 2016/07/21 02:10:31 good catch :)
bmilligan 2016/07/22 18:25:17 Acknowledged.
298 _formatters = [ 353 _formatters = [
354 new NamedConstructorFormatter(),
299 new FunctionFormatter(), 355 new FunctionFormatter(),
300 new MapFormatter(), 356 new MapFormatter(),
301 new IterableFormatter(), 357 new IterableFormatter(),
302 new MapEntryFormatter(), 358 new MapEntryFormatter(),
303 new IterableSpanFormatter(), 359 new IterableSpanFormatter(),
304 new ClassMetadataFormatter(), 360 new ClassMetadataFormatter(),
305 new HeritageClauseFormatter(), 361 new HeritageClauseFormatter(),
362 new ModuleLibraryFormatter(),
363 new LibraryFormatter(),
306 new ObjectFormatter(), 364 new ObjectFormatter(),
307 ]; 365 ];
308 } 366 }
309 367
310 String preview(object) { 368 String preview(object) {
311 try { 369 try {
312 if (object == null || 370 if (object == null ||
313 object is num || 371 object is num ||
314 object is String || 372 object is String ||
315 isNativeJavaScriptObject(object)) { 373 isNativeJavaScriptObject(object)) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 425
368 String preview(object) => getObjectTypeName(object); 426 String preview(object) => getObjectTypeName(object);
369 427
370 bool hasChildren(object) => true; 428 bool hasChildren(object) => true;
371 429
372 List<NameValuePair> children(object) { 430 List<NameValuePair> children(object) {
373 var properties = new LinkedHashSet<NameValuePair>(); 431 var properties = new LinkedHashSet<NameValuePair>();
374 // Set of property names used to avoid duplicates. 432 // Set of property names used to avoid duplicates.
375 addMetadataChildren(object, properties); 433 addMetadataChildren(object, properties);
376 434
377 /// Helper to add members walking up the prototype chain being careful
378 /// to avoid properties that are Dart methods.
379 var protoChain = <Object>[];
380 var current = object; 435 var current = object;
381 while (current != null && 436 var protoChain = getProtoChain(current);
382 !isNativeJavaScriptObject(current) &&
383 JS("bool", "# !== Object.prototype", current)) {
384 protoChain.add(current);
385 current = JSNative.getProperty(current, '__proto__');
386 }
387 437
388 // We walk the prototype chain for symbol properties because they take 438 // We walk the prototype chain for symbol properties because they take
389 // priority and are accessed instead of Dart properties according to Dart 439 // priority and are accessed instead of Dart properties according to Dart
390 // calling conventions. 440 // calling conventions.
391 // TODO(jacobr): where possible use the data stored by dart.setSignature 441 // TODO(jacobr): where possible use the data stored by dart.setSignature
392 // instead of walking the JavaScript object directly. 442 // instead of walking the JavaScript object directly.
393 for (current in protoChain) { 443 for (current in protoChain) {
394 for (var symbol in getOwnPropertySymbols(current)) { 444 for (var symbol in getOwnPropertySymbols(current)) {
395 var dartName = symbolName(symbol); 445 var dartName = symbolName(symbol);
396 if (hasMethod(object, dartName)) { 446 if (hasMethod(object, dartName)) {
397 continue; 447 continue;
398 } 448 }
399 // TODO(jacobr): find a cleaner solution than checking for dartx 449 // TODO(jacobr): find a cleaner solution than checking for dartx
400 String dartXPrefix = 'dartx.'; 450 String dartXPrefix = 'dartx.';
401 if (dartName.startsWith(dartXPrefix)) { 451 if (dartName.startsWith(dartXPrefix)) {
402 dartName = dartName.substring(dartXPrefix.length); 452 dartName = dartName.substring(dartXPrefix.length);
403 } else if (!dartName.startsWith('_')) { 453 } else if (!dartName.startsWith('_')) {
404 // Dart method extension names should either be from dartx or should 454 // Dart method extension names should either be from dartx or should
405 // start with an _ 455 // start with an _
406 continue; 456 continue;
407 } 457 }
408 var value; 458 var value = getPropertyValue(object, symbol);
409 try {
410 value = JSNative.getProperty(object, symbol);
411 } catch (e) {
412 value = '<Exception thrown> $e';
413 }
414 properties.add(new NameValuePair(name: dartName, value: value)); 459 properties.add(new NameValuePair(name: dartName, value: value));
415 } 460 }
416 } 461 }
417 462
418 for (current in protoChain) { 463 for (current in protoChain) {
419 // TODO(jacobr): optionally distinguish properties and fields so that 464 // TODO(jacobr): optionally distinguish properties and fields so that
420 // it is safe to expand untrusted objects without side effects. 465 // it is safe to expand untrusted objects without side effects.
421 var className = dart.getReifiedType(current).name; 466 var className = dart.getReifiedType(current).name;
422 for (var name in getOwnPropertyNames(current)) { 467 for (var name in getOwnPropertyNames(current)) {
423 if (_customNames.contains(name) || name == className) continue; 468 if (_customNames.contains(name) || name == className) continue;
424 if (hasMethod(object, name)) { 469 if (hasMethod(object, name)) {
425 continue; 470 continue;
426 } 471 }
427 var value; 472 var value = getPropertyValue(object, name);
428 try {
429 value = JSNative.getProperty(object, name);
430 } catch (e) {
431 value = '<Exception thrown> $e';
432 }
433 properties.add(new NameValuePair(name: name, value: value)); 473 properties.add(new NameValuePair(name: name, value: value));
434 } 474 }
435 } 475 }
436 476
437 return properties.toList(); 477 return properties.toList();
438 } 478 }
439 479
440 addMetadataChildren(object, Set<NameValuePair> ret) { 480 addMetadataChildren(object, Set<NameValuePair> ret) {
441 ret.add( 481 var value = new ClassMetadata(object);
442 new NameValuePair(name: '[[class]]', value: new ClassMetadata(object))); 482 ret.add(new NameValuePair(name: value.name, value: value));
Jacob 2016/07/21 02:10:31 btw the reason I have to create a ClassMetadata ob
bmilligan 2016/07/22 18:25:17 Acknowledged.
483 }
484
485 Object getPropertyValue(Object object, String name) {
Jacob 2016/07/21 02:10:31 call this safeGetProperty and make it a top level
bmilligan 2016/07/22 18:25:17 Done.
486 var value;
487 try {
488 value = JSNative.getProperty(object, name);
489 } catch (e) {
490 value = '<Exception thrown> $e';
491 }
492 return value;
493 }
494
495 /// Helper to add members walking up the prototype chain being careful
496 /// to avoid properties that are Dart methods.
497 List<Object> getProtoChain(var current) {
498 var protoChain = <Object>[];
499 while (current != null &&
500 !isNativeJavaScriptObject(current) &&
501 JS("bool", "# !== Object.prototype", current)) {
502 protoChain.add(current);
503 current = JSNative.getProperty(current, '__proto__');
504 }
505 return protoChain;
443 } 506 }
444 } 507 }
445 508
509 /// Formatter for module Dart Library objects.
510 class ModuleLibraryFormatter extends ObjectFormatter {
511 String libraryName;
512
513 accept(object) {
514 var current = object;
515 var protoChain = getProtoChain(current);
516 for (current in protoChain) {
517 for (var symbol in getOwnPropertySymbols(current)) {
518 if (symbolName(symbol) == 'dartLibraryName') {
Jacob 2016/07/21 02:10:31 you will be able to match the actual symbol instea
bmilligan 2016/07/22 18:25:18 Done.
519 libraryName = JSNative.getProperty(current, symbol);
520 return true;
521 }
522 }
523 }
524 return false;
525 }
526
527 bool hasChildren(object) => true;
528
529 String preview(object) {
530 var libraryNameArray = libraryName.split('/');
Jacob 2016/07/21 02:10:31 I think libraryNameParts would be cleaner
bmilligan 2016/07/22 18:25:17 Done.
531 if (libraryNameArray.length > 1) {
Jacob 2016/07/21 02:10:31 comment why you are stripping the last entry
bmilligan 2016/07/22 18:25:18 Done.
532 libraryNameArray[libraryNameArray.length - 1] = '';
Jacob 2016/07/21 02:10:31 libraryNameParts.last = ''
bmilligan 2016/07/22 18:25:18 '.last' cannot be used as a setter, which is why I
Jacob 2016/07/22 19:17:50 Acknowledged.
533 }
534 return 'Library Module: ${libraryNameArray.join('/')}';
535 }
536
537 List<NameValuePair> children(object) {
538 var properties = new LinkedHashSet<NameValuePair>();
539 for (var name in getOwnPropertyNames(object)) {
540 var value = JSNative.getProperty(object, name);
541 name = name.replaceAll('__', '/') + '.dart';
Jacob 2016/07/21 02:10:31 prefer string interoplation. So name = "${name.rep
bmilligan 2016/07/22 18:25:18 Done.
542 properties.add(new NameValuePair(
543 name: name, value: new Library(name, value), hideName: true));
544 }
545 return properties.toList();
546 }
547 }
548
549 /// Formatter for Dart Library objects.
550 class LibraryFormatter extends ObjectFormatter {
551 accept(object) => object is Library;
552
553 bool hasChildren(object) => true;
554
555 String preview(object) => object.name;
556
557 List<NameValuePair> children(object) {
558 var properties = new LinkedHashSet<NameValuePair>();
559 var entry = object.object;
560 for (var name in getOwnPropertyNames(entry)) {
561 var value = getPropertyValue(entry, name);
562 // TODO(bmilligan): Make a note on the corresponding class object that it
563 // has a generic type.
564 if (JSNative.getProperty(value, 'name') == 'makeGenericType') {
Jacob 2016/07/21 16:19:00 this is fragile. is there not an existing symbol t
Jennifer Messerly 2016/07/21 16:20:25 yeah there should be, I know we track type args on
bmilligan 2016/07/22 18:25:17 Done.
bmilligan 2016/07/22 18:25:17 Done.
565 continue;
566 } else if (value is Type) {
567 var classMetadata = new ClassMetadata(value);
568 properties.add(
569 new NameValuePair(name: classMetadata.name, value: classMetadata));
570 } else {
571 properties.add(new NameValuePair(name: name, value: value));
572 }
573 }
574 return properties.toList();
575 }
576 }
577
446 /// Formatter for Dart Function objects. 578 /// Formatter for Dart Function objects.
447 /// Dart functions happen to be regular JavaScript Function objects but 579 /// Dart functions happen to be regular JavaScript Function objects but
448 /// we can distinguish them based on whether they have been tagged with 580 /// we can distinguish them based on whether they have been tagged with
449 /// runtime type information. 581 /// runtime type information.
450 class FunctionFormatter extends Formatter { 582 class FunctionFormatter extends Formatter {
451 accept(object) { 583 accept(object) {
452 if (_typeof(object) != 'function') return false; 584 if (_typeof(object) != 'function') return false;
453 return dart.getReifiedType(object) != null; 585 return dart.getReifiedType(object) != null;
454 } 586 }
455 587
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
510 } 642 }
511 643
512 bool hasChildren(object) => true; 644 bool hasChildren(object) => true;
513 645
514 List<NameValuePair> children(object) { 646 List<NameValuePair> children(object) {
515 // TODO(jacobr): be lazier about enumerating contents of Iterables that 647 // TODO(jacobr): be lazier about enumerating contents of Iterables that
516 // are not the built in Set or List types. 648 // are not the built in Set or List types.
517 // TODO(jacobr): handle large Iterables better. 649 // TODO(jacobr): handle large Iterables better.
518 // TODO(jacobr): consider only using numeric indices 650 // TODO(jacobr): consider only using numeric indices
519 var ret = new LinkedHashSet<NameValuePair>(); 651 var ret = new LinkedHashSet<NameValuePair>();
520 ret.addAll(childrenHelper( 652 ret.addAll((new IterableSpan(0, object.length, object)).children());
Jacob 2016/07/21 16:18:59 remove unneeded extra set of parens.
bmilligan 2016/07/22 18:25:18 Done.
521 new IterableSpan(start: 0, end: object.length, iterable: object)));
522 // TODO(jacobr): provide a link to show regular class properties here. 653 // TODO(jacobr): provide a link to show regular class properties here.
523 // required for subclasses of iterable, etc. 654 // required for subclasses of iterable, etc.
524 addMetadataChildren(object, ret); 655 addMetadataChildren(object, ret);
525 return ret.toList(); 656 return ret.toList();
526 } 657 }
527 } 658 }
528 659
529 // This class does double duting displaying metadata for 660 // This class does double duting displaying metadata for
530 class ClassMetadataFormatter implements Formatter { 661 class ClassMetadataFormatter extends ObjectFormatter {
Jacob 2016/07/21 16:18:59 why is this now an extends instead of implements r
bmilligan 2016/07/22 18:25:18 There was a function I had in ObjectFormatter that
531 accept(object) => object is ClassMetadata; 662 accept(object) => object is ClassMetadata;
532 663
533 _getType(object) { 664 _getType(object) {
Jacob 2016/07/21 16:18:58 is the return type of this method Type?
bmilligan 2016/07/22 18:25:18 rtti.dart says getReifiedType "returns the runtime
Jacob 2016/07/22 19:17:50 Acknowledged.
534 if (object is Type) return object; 665 if (object is Type) return object;
535 return dart.getReifiedType(object); 666 return dart.getReifiedType(object);
536 } 667 }
537 668
538 String preview(object) { 669 String preview(object) {
539 ClassMetadata entry = object; 670 ClassMetadata entry = object;
540 return getTypeName(_getType(entry.object)); 671 var type =
672 entry.object is Type ? entry.object : dart.getReifiedType(entry.object);
673 var implements = dart.getImplements(type);
674 var ret = getTypeName(type);
675 if (implements != null) {
676 var typeNames = implements().map((type) => getTypeName(type));
677 return ret + ' implements ${typeNames.join(", ")}';
678 } else {
679 return ret;
680 }
541 } 681 }
542 682
543 bool hasChildren(object) => true; 683 bool hasChildren(object) => true;
544 684
545 List<NameValuePair> children(object) { 685 List<NameValuePair> children(object) {
546 ClassMetadata entry = object; 686 ClassMetadata entry = object;
687 var classObject = entry.object;
547 // TODO(jacobr): add other entries describing the class such as 688 // TODO(jacobr): add other entries describing the class such as
548 // links to the superclass, mixins, implemented interfaces, and methods. 689 // links to the superclass, mixins, implemented interfaces, and methods.
549 var type = _getType(entry.object); 690 var type = _getType(classObject);
550 var ret = <NameValuePair>[]; 691 var ret = <NameValuePair>[];
551 var implements = dart.getImplements(type); 692
552 if (implements != null) {
553 ret.add(new NameValuePair(
554 name: '[[Implements]]',
555 value: new HeritageClause('implements', implements())));
556 }
557 var mixins = dart.getMixins(type); 693 var mixins = dart.getMixins(type);
558 if (mixins != null && mixins.isNotEmpty) { 694 if (mixins != null && mixins.isNotEmpty) {
559 ret.add(new NameValuePair( 695 ret.add(new NameValuePair(
560 name: '[[Mixins]]', value: new HeritageClause('mixins', mixins))); 696 name: '[[Mixins]]', value: new HeritageClause('mixins', mixins)));
561 } 697 }
562 ret.add(new NameValuePair(
563 name: '[[JavaScript View]]',
564 value: entry.object,
565 config: JsonMLConfig.skipDart));
566 698
699 // Addition of NameValuePairs for static variables and named constructors.
700 for (var name in getOwnPropertyNames(classObject)) {
701 if (name == 'length' || name == 'name' || name == 'prototype') continue;
Jacob 2016/07/21 16:19:00 why are we removing length and name? I would add a
bmilligan 2016/07/22 18:25:17 Length is always = 0, and name is redundant as it'
702 var value = getPropertyValue(classObject, name);
703 for (var symbol in getOwnPropertySymbols(value)) {
704 if (symbolName(symbol) == 'isNamedConstructor') {
705 value = new NamedConstructor(value);
706 name = entry.name + '.' + name;
Jacob 2016/07/21 16:18:58 I think it is cleaner to write name = '${entry.nam
bmilligan 2016/07/22 18:25:18 Done.
707 }
708 }
709 ret.add(new NameValuePair(name: name, value: value));
710 }
711
712 // Addition of class methods.
713 var prototype = JS('var', '#["prototype"]', classObject);
714 if (prototype != null) {
715 for (var name in getOwnPropertyNames(prototype)) {
716 if (name == 'constructor' ||
717 name == 'new' ||
718 name == r'$identityHash') {
Jacob 2016/07/21 16:18:59 $identityHash is a little scary. Add a TODO to not
bmilligan 2016/07/22 18:25:18 Done. Is it because the name is fragile?
Jacob 2016/07/22 19:17:50 yeah. someone might well change it to $identity or
bmilligan 2016/07/22 20:10:24 Acknowledged.
719 continue;
720 }
721 // Simulate dart.bind by using dart.tag and tear off the function
722 // so it will be recognized by the FunctionFormatter.
723 var function = getPropertyValue(prototype, name);
724 var constructor = getPropertyValue(prototype, 'constructor');
725 for (var symbol in getOwnPropertySymbols(constructor)) {
726 if (symbolName(symbol) == 'sig') {
Jacob 2016/07/21 16:18:59 should not be using symbolName. You should be able
bmilligan 2016/07/22 18:25:18 Done.
727 var sigObj = getPropertyValue(constructor, symbol);
728 var value = getPropertyValue(sigObj, name);
729 if (getTypeName(dart.getReifiedType(value)) != 'Null') {
730 dart.tag(function, value);
731 ret.add(new NameValuePair(name: name, value: function));
732 }
733 }
734 }
735 }
736 }
567 // TODO(jacobr): provide a link to the base class or perhaps the entire 737 // TODO(jacobr): provide a link to the base class or perhaps the entire
568 // base class hierarchy as a flat list. 738 // base class hierarchy as a flat list.
569 739 // TODO(jacobr): add constructors, methods, extended class, and static
570 if (entry.object is! Type) {
571 ret.add(new NameValuePair(
572 name: '[[JavaScript Constructor]]',
573 value: JSNative.getProperty(entry.object, 'constructor'),
574 config: JsonMLConfig.skipDart));
575 // TODO(jacobr): add constructors, methods, extended class, and static
576 }
577 return ret; 740 return ret;
578 } 741 }
579 } 742 }
580 743
744 class NamedConstructorFormatter implements Formatter {
745 accept(object) => object is NamedConstructor;
746
747 // TODO(bmilligan): Display the signature of the named constructor as the
748 // preview.
749 String preview(object) => 'Named Constructor';
bmilligan 2016/07/21 01:59:27 I'm working on getting this to display the signatu
Jacob 2016/07/21 16:18:59 Sounds good.
bmilligan 2016/07/22 18:25:18 Acknowledged.
750
751 bool hasChildren(object) => true;
752
753 List<NameValuePair> children(object) => <NameValuePair>[
754 new NameValuePair(
755 name: 'JavaScript Function',
756 value: object,
757 config: JsonMLConfig.skipDart)
758 ];
759 }
760
581 /// Formatter for synthetic MapEntry objects used to display contents of a Map 761 /// Formatter for synthetic MapEntry objects used to display contents of a Map
582 /// cleanly. 762 /// cleanly.
583 class MapEntryFormatter implements Formatter { 763 class MapEntryFormatter implements Formatter {
584 accept(object) => object is MapEntry; 764 accept(object) => object is MapEntry;
585 765
586 String preview(object) { 766 String preview(object) {
587 MapEntry entry = object; 767 MapEntry entry = object;
588 return '${safePreview(entry.key)} => ${safePreview(entry.value)}'; 768 return '${safePreview(entry.key)} => ${safePreview(entry.value)}';
589 } 769 }
590 770
(...skipping 27 matching lines...) Expand all
618 return ret; 798 return ret;
619 } 799 }
620 } 800 }
621 801
622 /// Formatter for synthetic IterableSpan objects used to display contents of 802 /// Formatter for synthetic IterableSpan objects used to display contents of
623 /// an Iterable cleanly. 803 /// an Iterable cleanly.
624 class IterableSpanFormatter implements Formatter { 804 class IterableSpanFormatter implements Formatter {
625 accept(object) => object is IterableSpan; 805 accept(object) => object is IterableSpan;
626 806
627 String preview(object) { 807 String preview(object) {
628 IterableSpan entry = object;
629 return '[${object.start}...${object.end-1}]'; 808 return '[${object.start}...${object.end-1}]';
630 } 809 }
631 810
632 bool hasChildren(object) => true; 811 bool hasChildren(object) => true;
633 812
634 List<NameValuePair> children(object) => childrenHelper(object); 813 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 } 814 }
673 815
674 /// This entry point is automatically invoked by the code generated by 816 /// This entry point is automatically invoked by the code generated by
675 /// Dart Dev Compiler 817 /// Dart Dev Compiler
676 registerDevtoolsFormatter() { 818 registerDevtoolsFormatter() {
677 var formatters = [_devtoolsFormatter]; 819 var formatters = [_devtoolsFormatter];
678 JS('', 'dart.global.devtoolsFormatters = #', formatters); 820 JS('', 'dart.global.devtoolsFormatters = #', formatters);
679 } 821 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698