Chromium Code Reviews| Index: tool/input_sdk/private/debugger.dart |
| diff --git a/tool/input_sdk/private/debugger.dart b/tool/input_sdk/private/debugger.dart |
| index 252b2c84e9ccd1fe459af121085b60105bedbfa7..fc90f6067a4be89b7b9732f253fec7aed14d96d7 100644 |
| --- a/tool/input_sdk/private/debugger.dart |
| +++ b/tool/input_sdk/private/debugger.dart |
| @@ -31,7 +31,7 @@ class JsonMLConfig { |
| } |
| int _maxSpanLength = 100; |
| - |
| +Symbol isClass = JS('Symbol', 'Symbol("isClass")'); |
|
bmilligan
2016/08/02 01:12:44
Using 'new Symbol('isClass') in Dart followed by J
|
| var _devtoolsFormatter = new JsonMLFormatter(new DartFormatter()); |
| String _typeof(object) => JS('String', 'typeof #', object); |
| @@ -51,6 +51,12 @@ class JSNative { |
| JS('', '#[#]=#', object, name, value); |
| } |
| +void addMetadataChildren(object, Set<NameValuePair> ret) { |
| + JSNative.setProperty(object, isClass, true); |
| + ret.add( |
| + new NameValuePair(name: getTypeName(_getType(object)), value: object)); |
| +} |
| + |
| String getObjectTypeName(object) { |
| var reifiedType = dart.getReifiedType(object); |
| if (reifiedType == null) { |
| @@ -73,6 +79,9 @@ String getTypeName(Type type) { |
| return name; |
| } |
| +Object _getType(object) => |
| + object is Type ? object : dart.getReifiedType(object); |
| + |
| String safePreview(object) { |
| try { |
| var preview = _devtoolsFormatter._simpleFormatter.preview(object); |
| @@ -183,17 +192,6 @@ class NamedConstructor { |
| final Object object; |
| } |
| -class ClassMetadata { |
| - ClassMetadata(this.object, {this.name}); |
| - |
| - final Object object; |
| - final String name; |
| - |
| - String get typeName => |
| - name ?? |
| - getTypeName(object is Type ? object : dart.getReifiedType(object)); |
| -} |
| - |
| class HeritageClause { |
| HeritageClause(this.name, this.types); |
| @@ -201,7 +199,7 @@ class HeritageClause { |
| final List types; |
| } |
| -Object safeGetProperty(Object protoChain, String name) { |
| +Object safeGetProperty(Object protoChain, Object name) { |
| try { |
| return JSNative.getProperty(protoChain, name); |
| } catch (e) { |
| @@ -371,14 +369,14 @@ class DartFormatter { |
| // The order of formatters matters as formatters earlier in the list take |
| // precedence. |
| _formatters = [ |
| + new ClassFormatter(), |
| new NamedConstructorFormatter(), |
| - new FunctionFormatter(), |
| new MapFormatter(), |
| new IterableFormatter(), |
| - new MapEntryFormatter(), |
| new IterableSpanFormatter(), |
| + new MapEntryFormatter(), |
| new StackTraceFormatter(), |
| - new ClassMetadataFormatter(), |
| + new FunctionFormatter(), |
| new HeritageClauseFormatter(), |
| new LibraryModuleFormatter(), |
| new LibraryFormatter(), |
| @@ -504,15 +502,10 @@ class ObjectFormatter extends Formatter { |
| return properties.toList(); |
| } |
| - |
| - addMetadataChildren(object, Set<NameValuePair> ret) { |
| - var child = new ClassMetadata(object); |
| - ret.add(new NameValuePair(name: child.typeName, value: child)); |
| - } |
| } |
| /// Formatter for module Dart Library objects. |
| -class LibraryModuleFormatter extends ObjectFormatter { |
| +class LibraryModuleFormatter implements Formatter { |
| String libraryName; |
| accept(object) { |
| @@ -548,8 +541,7 @@ class LibraryModuleFormatter extends ObjectFormatter { |
| } |
| } |
| -/// Formatter for Dart Library objects. |
| -class LibraryFormatter extends ObjectFormatter { |
| +class LibraryFormatter implements Formatter { |
| var genericParameters = new HashMap<String, String>(); |
| accept(object) => object is Library; |
| @@ -599,9 +591,9 @@ class LibraryFormatter extends ObjectFormatter { |
| var parameterName = '$name\$'; |
| if (genericParameters.keys.contains(parameterName)) { |
| typeName = '$typeName<${genericParameters[parameterName]}>'; |
| + JSNative.setProperty(child, 'genericTypeName', typeName); |
| } |
| - return new NameValuePair( |
| - name: typeName, value: new ClassMetadata(child, name: typeName)); |
| + return new NameValuePair(name: typeName, value: child); |
| } |
| } |
| @@ -609,7 +601,7 @@ class LibraryFormatter extends ObjectFormatter { |
| /// Dart functions happen to be regular JavaScript Function objects but |
| /// we can distinguish them based on whether they have been tagged with |
| /// runtime type information. |
| -class FunctionFormatter extends Formatter { |
| +class FunctionFormatter implements Formatter { |
| accept(object) { |
| if (_typeof(object) != 'function') return false; |
| return dart.getReifiedType(object) != null; |
| @@ -631,7 +623,7 @@ class FunctionFormatter extends Formatter { |
| } |
| /// Formatter for Dart Map objects. |
| -class MapFormatter extends ObjectFormatter { |
| +class MapFormatter implements Formatter { |
| accept(object) => object is Map; |
| bool hasChildren(object) => true; |
| @@ -658,7 +650,7 @@ class MapFormatter extends ObjectFormatter { |
| } |
| /// Formatter for Dart Iterable objects including List and Set. |
| -class IterableFormatter extends ObjectFormatter { |
| +class IterableFormatter implements Formatter { |
| bool accept(object) => object is Iterable; |
| String preview(object) { |
| @@ -687,86 +679,6 @@ class IterableFormatter extends ObjectFormatter { |
| } |
| } |
| -// This class does double duting displaying metadata for |
| -class ClassMetadataFormatter implements Formatter { |
| - accept(object) => object is ClassMetadata; |
| - |
| - Object _getType(object) { |
| - if (object is Type) return object; |
| - return dart.getReifiedType(object); |
| - } |
| - |
| - String preview(object) { |
| - ClassMetadata entry = object; |
| - var type = |
| - entry.object is Type ? entry.object : dart.getReifiedType(entry.object); |
| - var implements = dart.getImplements(type); |
| - if (implements != null) { |
| - var typeNames = implements().map(getTypeName); |
| - return '${entry.typeName} implements ${typeNames.join(", ")}'; |
| - } else { |
| - return entry.typeName; |
| - } |
| - } |
| - |
| - bool hasChildren(object) => true; |
| - |
| - List<NameValuePair> children(object) { |
| - ClassMetadata entry = object; |
| - var classObject = entry.object; |
| - // TODO(jacobr): add other entries describing the class such as |
| - // links to the superclass, mixins, implemented interfaces, and methods. |
| - var type = _getType(classObject); |
| - var children = <NameValuePair>[]; |
| - |
| - var mixins = dart.getMixins(type); |
| - if (mixins != null && mixins.isNotEmpty) { |
| - children.add(new NameValuePair( |
| - name: '[[Mixins]]', value: new HeritageClause('mixins', mixins))); |
| - } |
| - |
| - var hiddenProperties = ['length', 'name', 'prototype']; |
| - // Addition of NameValuePairs for static variables and named constructors. |
| - for (var name in getOwnPropertyNames(classObject)) { |
| - // TODO(bmilligan): Perform more principled checks to filter out spurious |
| - // members. |
| - if (hiddenProperties.contains(name)) continue; |
| - var value = safeGetProperty(classObject, name); |
| - if (value != null && dart.getIsNamedConstructor(value) != null) { |
| - value = new NamedConstructor(value); |
| - name = '${entry.typeName}.$name'; |
| - } |
| - children.add(new NameValuePair(name: name, value: value)); |
| - } |
| - |
| - // TODO(bmilligan): Replace the hard coding of $identityHash. |
| - var hiddenPrototypeProperties = ['constructor', 'new', r'$identityHash']; |
| - // Addition of class methods. |
| - var prototype = JS('var', '#["prototype"]', classObject); |
| - if (prototype != null) { |
| - for (var name in getOwnPropertyNames(prototype)) { |
| - if (hiddenPrototypeProperties.contains(name)) continue; |
| - // Simulate dart.bind by using dart.tag and tear off the function |
| - // so it will be recognized by the FunctionFormatter. |
| - var function = safeGetProperty(prototype, name); |
| - var constructor = safeGetProperty(prototype, 'constructor'); |
| - var sigObj = dart.getMethodSig(constructor); |
| - if (sigObj != null) { |
| - var value = safeGetProperty(sigObj, name); |
| - if (getTypeName(dart.getReifiedType(value)) != 'Null') { |
| - dart.tag(function, value); |
| - children.add(new NameValuePair(name: name, value: function)); |
| - } |
| - } |
| - } |
| - } |
| - // TODO(jacobr): provide a link to the base class or perhaps the entire |
| - // base class hierarchy as a flat list. |
| - // TODO(jacobr): add constructors, methods, extended class, and static |
| - return children; |
| - } |
| -} |
| - |
| class NamedConstructorFormatter implements Formatter { |
| accept(object) => object is NamedConstructor; |
| @@ -819,7 +731,8 @@ class HeritageClauseFormatter implements Formatter { |
| HeritageClause clause = object; |
| var children = <NameValuePair>[]; |
| for (var type in clause.types) { |
| - children.add(new NameValuePair(value: new ClassMetadata(type))); |
| + JSNative.setProperty(type, isClass, true); |
| + children.add(new NameValuePair(value: type)); |
| } |
| return children; |
| } |
| @@ -858,6 +771,78 @@ class StackTraceFormatter implements Formatter { |
| .toList(); |
| } |
| +class ClassFormatter implements Formatter { |
| + accept(object) => object is Type || safeGetProperty(object, isClass) == true; |
| + |
| + String preview(object) { |
| + // TODO(bmilligan): Tag classes with generic types with a Symbol at their |
| + // creation so they can be recognized by the ClassFormatter. |
| + var typeName = safeGetProperty(object, 'genericTypeName'); |
| + if (typeName != null) return typeName; |
| + var type = _getType(object); |
| + var implements = dart.getImplements(type); |
| + typeName = getTypeName(type); |
| + if (implements != null) { |
| + var typeNames = implements().map(getTypeName); |
| + return '${typeName} implements ${typeNames.join(", ")}'; |
| + } else { |
| + return typeName; |
| + } |
| + } |
| + |
| + bool hasChildren(object) => true; |
| + |
| + List<NameValuePair> children(object) { |
| + // TODO(jacobr): add other entries describing the class such as |
| + // links to the superclass, mixins, implemented interfaces, and methods. |
| + var type = _getType(object); |
| + var children = <NameValuePair>[]; |
| + var typeName = getTypeName(_getType(object)); |
| + var mixins = dart.getMixins(type); |
| + if (mixins != null && mixins.isNotEmpty) { |
| + children.add(new NameValuePair( |
| + name: '[[Mixins]]', value: new HeritageClause('mixins', mixins))); |
| + } |
| + |
| + var hiddenProperties = ['length', 'name', 'prototype', 'genericTypeName']; |
| + // Addition of NameValuePairs for static variables and named constructors. |
| + for (var name in getOwnPropertyNames(object)) { |
| + // TODO(bmilligan): Perform more principled checks to filter out spurious |
| + // members. |
| + if (hiddenProperties.contains(name)) continue; |
| + var value = safeGetProperty(object, name); |
| + if (value != null && dart.getIsNamedConstructor(value) != null) { |
| + value = new NamedConstructor(value); |
| + name = '${typeName}.$name'; |
| + } |
| + children.add(new NameValuePair(name: name, value: value)); |
| + } |
| + |
| + // TODO(bmilligan): Replace the hard coding of $identityHash. |
| + var hiddenPrototypeProperties = ['constructor', 'new', r'$identityHash']; |
| + // Addition of class methods. |
| + var prototype = JS('var', '#["prototype"]', object); |
| + if (prototype != null) { |
| + for (var name in getOwnPropertyNames(prototype)) { |
| + if (hiddenPrototypeProperties.contains(name)) continue; |
| + // Simulate dart.bind by using dart.tag and tear off the function |
| + // so it will be recognized by the FunctionFormatter. |
| + var function = safeGetProperty(prototype, name); |
| + var constructor = safeGetProperty(prototype, 'constructor'); |
| + var sigObj = dart.getMethodSig(constructor); |
| + if (sigObj != null) { |
| + var value = safeGetProperty(sigObj, name); |
| + if (getTypeName(dart.getReifiedType(value)) != 'Null') { |
| + dart.tag(function, value); |
| + children.add(new NameValuePair(name: name, value: function)); |
| + } |
| + } |
| + } |
| + } |
| + return children; |
| + } |
| +} |
| + |
| /// This entry point is automatically invoked by the code generated by |
| /// Dart Dev Compiler |
| registerDevtoolsFormatter() { |