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

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: Pub upgrade 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 | « tool/input_sdk/private/ddc_runtime/rtti.dart ('k') | no next file » | 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';
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 name: '[${i}...${subSpan.end - 1}]', 163 name: '[${i}...${subSpan.end - 1}]',
164 value: subSpan, 164 value: subSpan,
165 hideName: true)); 165 hideName: true));
166 } 166 }
167 } 167 }
168 } 168 }
169 return ret; 169 return ret;
170 } 170 }
171 } 171 }
172 172
173 class Library {
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;
184 }
185
173 class ClassMetadata { 186 class ClassMetadata {
174 ClassMetadata(this.object); 187 ClassMetadata(this.object);
175 188
176 final Object object; 189 final Object object;
190 String get name =>
191 getTypeName(object is Type ? object : dart.getReifiedType(object));
177 } 192 }
178 193
179 class HeritageClause { 194 class HeritageClause {
180 HeritageClause(this.name, this.types); 195 HeritageClause(this.name, this.types);
181 196
182 final String name; 197 final String name;
183 final List types; 198 final List types;
184 } 199 }
185 200
186 /// Class to simplify building the JsonML objects expected by the 201 /// Class to simplify building the JsonML objects expected by the
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 bool accept(object); 341 bool accept(object);
327 String preview(object); 342 String preview(object);
328 bool hasChildren(object); 343 bool hasChildren(object);
329 List<NameValuePair> children(object); 344 List<NameValuePair> children(object);
330 } 345 }
331 346
332 class DartFormatter { 347 class DartFormatter {
333 List<Formatter> _formatters; 348 List<Formatter> _formatters;
334 349
335 DartFormatter() { 350 DartFormatter() {
336 // 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
337 // precidence. 352 // precedence.
338 _formatters = [ 353 _formatters = [
354 new NamedConstructorFormatter(),
339 new FunctionFormatter(), 355 new FunctionFormatter(),
340 new MapFormatter(), 356 new MapFormatter(),
341 new IterableFormatter(), 357 new IterableFormatter(),
342 new MapEntryFormatter(), 358 new MapEntryFormatter(),
343 new IterableSpanFormatter(), 359 new IterableSpanFormatter(),
344 new ClassMetadataFormatter(), 360 new ClassMetadataFormatter(),
345 new HeritageClauseFormatter(), 361 new HeritageClauseFormatter(),
362 new ModuleLibraryFormatter(),
363 new LibraryFormatter(),
346 new ObjectFormatter(), 364 new ObjectFormatter(),
347 ]; 365 ];
348 } 366 }
349 367
350 String preview(object) { 368 String preview(object) {
351 try { 369 try {
352 if (object == null || 370 if (object == null ||
353 object is num || 371 object is num ||
354 object is String || 372 object is String ||
355 isNativeJavaScriptObject(object)) { 373 isNativeJavaScriptObject(object)) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 425
408 String preview(object) => getObjectTypeName(object); 426 String preview(object) => getObjectTypeName(object);
409 427
410 bool hasChildren(object) => true; 428 bool hasChildren(object) => true;
411 429
412 List<NameValuePair> children(object) { 430 List<NameValuePair> children(object) {
413 var properties = new LinkedHashSet<NameValuePair>(); 431 var properties = new LinkedHashSet<NameValuePair>();
414 // Set of property names used to avoid duplicates. 432 // Set of property names used to avoid duplicates.
415 addMetadataChildren(object, properties); 433 addMetadataChildren(object, properties);
416 434
417 /// Helper to add members walking up the prototype chain being careful
418 /// to avoid properties that are Dart methods.
419 var protoChain = <Object>[];
420 var current = object; 435 var current = object;
421 while (current != null && 436 var protoChain = getProtoChain(current);
422 !isNativeJavaScriptObject(current) &&
423 JS("bool", "# !== Object.prototype", current)) {
424 protoChain.add(current);
425 current = JSNative.getProperty(current, '__proto__');
426 }
427 437
428 // We walk the prototype chain for symbol properties because they take 438 // We walk the prototype chain for symbol properties because they take
429 // priority and are accessed instead of Dart properties according to Dart 439 // priority and are accessed instead of Dart properties according to Dart
430 // calling conventions. 440 // calling conventions.
431 // TODO(jacobr): where possible use the data stored by dart.setSignature 441 // TODO(jacobr): where possible use the data stored by dart.setSignature
432 // instead of walking the JavaScript object directly. 442 // instead of walking the JavaScript object directly.
433 for (current in protoChain) { 443 for (current in protoChain) {
434 for (var symbol in getOwnPropertySymbols(current)) { 444 for (var symbol in getOwnPropertySymbols(current)) {
435 var dartName = symbolName(symbol); 445 var dartName = symbolName(symbol);
436 if (hasMethod(object, dartName)) { 446 if (hasMethod(object, dartName)) {
437 continue; 447 continue;
438 } 448 }
439 // TODO(jacobr): find a cleaner solution than checking for dartx 449 // TODO(jacobr): find a cleaner solution than checking for dartx
440 String dartXPrefix = 'dartx.'; 450 String dartXPrefix = 'dartx.';
441 if (dartName.startsWith(dartXPrefix)) { 451 if (dartName.startsWith(dartXPrefix)) {
442 dartName = dartName.substring(dartXPrefix.length); 452 dartName = dartName.substring(dartXPrefix.length);
443 } else if (!dartName.startsWith('_')) { 453 } else if (!dartName.startsWith('_')) {
444 // Dart method extension names should either be from dartx or should 454 // Dart method extension names should either be from dartx or should
445 // start with an _ 455 // start with an _
446 continue; 456 continue;
447 } 457 }
448 var value; 458 var value = getPropertyValue(object, symbol);
449 try {
450 value = JSNative.getProperty(object, symbol);
451 } catch (e) {
452 value = '<Exception thrown> $e';
453 }
454 properties.add(new NameValuePair(name: dartName, value: value)); 459 properties.add(new NameValuePair(name: dartName, value: value));
455 } 460 }
456 } 461 }
457 462
458 for (current in protoChain) { 463 for (current in protoChain) {
459 // TODO(jacobr): optionally distinguish properties and fields so that 464 // TODO(jacobr): optionally distinguish properties and fields so that
460 // it is safe to expand untrusted objects without side effects. 465 // it is safe to expand untrusted objects without side effects.
461 var className = dart.getReifiedType(current).name; 466 var className = dart.getReifiedType(current).name;
462 for (var name in getOwnPropertyNames(current)) { 467 for (var name in getOwnPropertyNames(current)) {
463 if (_customNames.contains(name) || name == className) continue; 468 if (_customNames.contains(name) || name == className) continue;
464 if (hasMethod(object, name)) { 469 if (hasMethod(object, name)) {
465 continue; 470 continue;
466 } 471 }
467 var value; 472 var value = getPropertyValue(object, name);
468 try {
469 value = JSNative.getProperty(object, name);
470 } catch (e) {
471 value = '<Exception thrown> $e';
472 }
473 properties.add(new NameValuePair(name: name, value: value)); 473 properties.add(new NameValuePair(name: name, value: value));
474 } 474 }
475 } 475 }
476 476
477 return properties.toList(); 477 return properties.toList();
478 } 478 }
479 479
480 addMetadataChildren(object, Set<NameValuePair> ret) { 480 addMetadataChildren(object, Set<NameValuePair> ret) {
481 ret.add( 481 var value = new ClassMetadata(object);
482 new NameValuePair(name: '[[class]]', value: new ClassMetadata(object))); 482 ret.add(new NameValuePair(name: value.name, value: value));
483 }
484
485 Object getPropertyValue(Object object, String name) {
Alan Knight 2016/07/21 17:44:48 It's better to avoid "get" as a prefix (even thoug
bmilligan 2016/07/22 18:25:19 Jacob suggested safeGetProperty. Are you referring
Alan Knight 2016/07/22 20:28:41 safeGetProperty seems reasonable. I was referring
bmilligan 2016/07/22 20:47:40 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.
Alan Knight 2016/07/21 17:44:49 What does the comment mean about being careful to
bmilligan 2016/07/22 18:25:18 This function existed previously, I just moved it
Alan Knight 2016/07/22 20:28:41 I'm suspicious it got moved to the wrong place som
bmilligan 2016/07/22 20:47:40 Done.
497 List<Object> getProtoChain(var current) {
Alan Knight 2016/07/21 17:44:49 Don't put "var" on a method parameter, either leav
bmilligan 2016/07/22 18:25:19 Done.
498 var protoChain = <Object>[];
499 while (current != null &&
500 !isNativeJavaScriptObject(current) &&
501 JS("bool", "# !== Object.prototype", current)) {
502 protoChain.add(current);
Alan Knight 2016/07/21 17:44:49 Naming an input parameter "current" feels odd. Al
bmilligan 2016/07/22 18:25:19 Done.
503 current = JSNative.getProperty(current, '__proto__');
504 }
505 return protoChain;
483 } 506 }
484 } 507 }
485 508
509 /// Formatter for module Dart Library objects.
Alan Knight 2016/07/21 17:44:49 What's the difference between a module dart librar
bmilligan 2016/07/22 18:25:18 The dart library module is an object that contains
Alan Knight 2016/07/22 20:28:41 Acknowledged.
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) {
Alan Knight 2016/07/21 17:44:49 Using a for loop variable that's declared and init
bmilligan 2016/07/22 18:25:19 Yeah, I switched this part to be identifiable by s
517 for (var symbol in getOwnPropertySymbols(current)) {
518 if (symbolName(symbol) == 'dartLibraryName') {
519 libraryName = JSNative.getProperty(current, symbol);
Alan Knight 2016/07/21 17:44:49 We now have a function for this, so we should use
bmilligan 2016/07/22 18:25:19 Done.
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('/');
Alan Knight 2016/07/21 17:44:49 Better to just call this "libraryNames", makes the
bmilligan 2016/07/22 18:25:19 Done.
531 if (libraryNameArray.length > 1) {
532 libraryNameArray[libraryNameArray.length - 1] = '';
533 }
534 return 'Library Module: ${libraryNameArray.join('/')}';
535 }
536
537 List<NameValuePair> children(object) {
538 var properties = new LinkedHashSet<NameValuePair>();
Alan Knight 2016/07/21 17:44:49 These are linked because we want to preserve the J
bmilligan 2016/07/22 18:25:19 The JS order is already alphabetical. It's nice to
Alan Knight 2016/07/22 20:28:41 Acknowledged.
539 for (var name in getOwnPropertyNames(object)) {
540 var value = JSNative.getProperty(object, name);
Alan Knight 2016/07/21 17:44:49 Shouldn't this, and similarly below be calling our
bmilligan 2016/07/22 18:25:18 Done.
541 name = name.replaceAll('__', '/') + '.dart';
Alan Knight 2016/07/21 17:44:49 A comment for the replacement would be good.
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>();
Alan Knight 2016/07/21 17:44:49 Should this just be called "children"?
bmilligan 2016/07/22 18:25:18 Done.
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') {
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
486 /// Formatter for Dart Function objects. 578 /// Formatter for Dart Function objects.
487 /// Dart functions happen to be regular JavaScript Function objects but 579 /// Dart functions happen to be regular JavaScript Function objects but
488 /// 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
489 /// runtime type information. 581 /// runtime type information.
490 class FunctionFormatter extends Formatter { 582 class FunctionFormatter extends Formatter {
491 accept(object) { 583 accept(object) {
492 if (_typeof(object) != 'function') return false; 584 if (_typeof(object) != 'function') return false;
493 return dart.getReifiedType(object) != null; 585 return dart.getReifiedType(object) != null;
494 } 586 }
495 587
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
559 var ret = new LinkedHashSet<NameValuePair>(); 651 var ret = new LinkedHashSet<NameValuePair>();
560 ret.addAll((new IterableSpan(0, object.length, object)).children()); 652 ret.addAll((new IterableSpan(0, object.length, object)).children());
561 // TODO(jacobr): provide a link to show regular class properties here. 653 // TODO(jacobr): provide a link to show regular class properties here.
562 // required for subclasses of iterable, etc. 654 // required for subclasses of iterable, etc.
563 addMetadataChildren(object, ret); 655 addMetadataChildren(object, ret);
564 return ret.toList(); 656 return ret.toList();
565 } 657 }
566 } 658 }
567 659
568 // This class does double duting displaying metadata for 660 // This class does double duting displaying metadata for
569 class ClassMetadataFormatter implements Formatter { 661 class ClassMetadataFormatter extends ObjectFormatter {
570 accept(object) => object is ClassMetadata; 662 accept(object) => object is ClassMetadata;
571 663
572 _getType(object) { 664 _getType(object) {
573 if (object is Type) return object; 665 if (object is Type) return object;
574 return dart.getReifiedType(object); 666 return dart.getReifiedType(object);
575 } 667 }
576 668
577 String preview(object) { 669 String preview(object) {
578 ClassMetadata entry = object; 670 ClassMetadata entry = object;
579 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);
Alan Knight 2016/07/21 17:44:48 var typeName?
bmilligan 2016/07/22 18:25:19 Done.
675 if (implements != null) {
676 var typeNames = implements().map((type) => getTypeName(type));
Alan Knight 2016/07/21 17:44:49 If you're just calling a one argument function/met
bmilligan 2016/07/22 18:25:18 Done.
677 return ret + ' implements ${typeNames.join(", ")}';
Alan Knight 2016/07/21 17:44:49 Really nitpicking it's slightly better to use an i
bmilligan 2016/07/22 18:25:19 Done.
678 } else {
679 return ret;
680 }
580 } 681 }
581 682
582 bool hasChildren(object) => true; 683 bool hasChildren(object) => true;
583 684
584 List<NameValuePair> children(object) { 685 List<NameValuePair> children(object) {
585 ClassMetadata entry = object; 686 ClassMetadata entry = object;
687 var classObject = entry.object;
586 // TODO(jacobr): add other entries describing the class such as 688 // TODO(jacobr): add other entries describing the class such as
587 // links to the superclass, mixins, implemented interfaces, and methods. 689 // links to the superclass, mixins, implemented interfaces, and methods.
588 var type = _getType(entry.object); 690 var type = _getType(classObject);
589 var ret = <NameValuePair>[]; 691 var ret = <NameValuePair>[];
Alan Knight 2016/07/21 17:44:49 Also better as "children"
bmilligan 2016/07/22 18:25:19 Done.
590 var implements = dart.getImplements(type); 692
591 if (implements != null) {
592 ret.add(new NameValuePair(
593 name: '[[Implements]]',
594 value: new HeritageClause('implements', implements())));
595 }
596 var mixins = dart.getMixins(type); 693 var mixins = dart.getMixins(type);
597 if (mixins != null && mixins.isNotEmpty) { 694 if (mixins != null && mixins.isNotEmpty) {
598 ret.add(new NameValuePair( 695 ret.add(new NameValuePair(
599 name: '[[Mixins]]', value: new HeritageClause('mixins', mixins))); 696 name: '[[Mixins]]', value: new HeritageClause('mixins', mixins)));
600 } 697 }
601 ret.add(new NameValuePair(
602 name: '[[JavaScript View]]',
603 value: entry.object,
604 config: JsonMLConfig.skipDart));
605 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;
Alan Knight 2016/07/21 17:44:49 This would be better in a separate list of propert
bmilligan 2016/07/22 18:25:18 Done.
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;
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' ||
Alan Knight 2016/07/21 17:44:49 Also better in a separate list.
bmilligan 2016/07/22 18:25:19 Done.
718 name == r'$identityHash') {
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');
Alan Knight 2016/07/21 17:44:49 Also, I would think, call our wrapper for this. I
bmilligan 2016/07/22 18:25:18 Done.
725 for (var symbol in getOwnPropertySymbols(constructor)) {
726 if (symbolName(symbol) == 'sig') {
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 }
606 // 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
607 // base class hierarchy as a flat list. 738 // base class hierarchy as a flat list.
608 739 // TODO(jacobr): add constructors, methods, extended class, and static
609 if (entry.object is! Type) {
610 ret.add(new NameValuePair(
611 name: '[[JavaScript Constructor]]',
612 value: JSNative.getProperty(entry.object, 'constructor'),
613 config: JsonMLConfig.skipDart));
614 // TODO(jacobr): add constructors, methods, extended class, and static
615 }
616 return ret; 740 return ret;
617 } 741 }
618 } 742 }
619 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';
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
620 /// 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
621 /// cleanly. 762 /// cleanly.
622 class MapEntryFormatter implements Formatter { 763 class MapEntryFormatter implements Formatter {
623 accept(object) => object is MapEntry; 764 accept(object) => object is MapEntry;
624 765
625 String preview(object) { 766 String preview(object) {
626 MapEntry entry = object; 767 MapEntry entry = object;
627 return '${safePreview(entry.key)} => ${safePreview(entry.value)}'; 768 return '${safePreview(entry.key)} => ${safePreview(entry.value)}';
628 } 769 }
629 770
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
671 812
672 List<NameValuePair> children(object) => object.children(); 813 List<NameValuePair> children(object) => object.children();
673 } 814 }
674 815
675 /// This entry point is automatically invoked by the code generated by 816 /// This entry point is automatically invoked by the code generated by
676 /// Dart Dev Compiler 817 /// Dart Dev Compiler
677 registerDevtoolsFormatter() { 818 registerDevtoolsFormatter() {
678 var formatters = [_devtoolsFormatter]; 819 var formatters = [_devtoolsFormatter];
679 JS('', 'dart.global.devtoolsFormatters = #', formatters); 820 JS('', 'dart.global.devtoolsFormatters = #', formatters);
680 } 821 }
OLDNEW
« no previous file with comments | « tool/input_sdk/private/ddc_runtime/rtti.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698