// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library dart._debugger;

import 'dart:_foreign_helper' show JS;
import 'dart:_runtime' as dart;
import 'dart:core';
import 'dart:collection';
import 'dart:html' as html;
import 'dart:math';

/// JsonMLConfig object to pass to devtools to specify how an Object should
/// be displayed. skipDart signals that an object should not be formatted
/// by the Dart formatter. This is used to specify that an Object
/// should just be displayed using the regular JavaScript view instead of a
/// custom Dart view. For example, this is used to display the JavaScript view
/// of a Dart Function as a child of the regular Function object. keyToString
/// signals that a map key object should have its toString() displayed by
/// the Dart formatter.
///
/// We'd like this to be an enum, but we can't because it's a dev_compiler bug.
class JsonMLConfig {
  const JsonMLConfig(this.name);

  final String name;
  static const none = const JsonMLConfig("none");
  static const skipDart = const JsonMLConfig("skipDart");
  static const keyToString = const JsonMLConfig("keyToString");
  static const asClass = const JsonMLConfig("asClass");
}

int _maxSpanLength = 100;
var _devtoolsFormatter = new JsonMLFormatter(new DartFormatter());

String _typeof(object) => JS('String', 'typeof #', object);

List<String> getOwnPropertyNames(object) => JS('List<String>',
    'dart.list(Object.getOwnPropertyNames(#), #)', object, String);

List getOwnPropertySymbols(object) =>
    JS('List', 'Object.getOwnPropertySymbols(#)', object);

// TODO(jacobr): move this to dart:js and fully implement.
class JSNative {
  // Name may be a String or a Symbol.
  static getProperty(object, name) => JS('', '#[#]', object, name);
  // Name may be a String or a Symbol.
  static setProperty(object, name, value) =>
      JS('', '#[#]=#', object, name, value);
}

void addMetadataChildren(object, Set<NameValuePair> ret) {
  ret.add(new NameValuePair(
      name: "[[class]]",
      value: dart.getReifiedType(object),
      config: JsonMLConfig.asClass));
}

/// Add properties from a signature definition [sig] for [object].
/// Walk the prototype chain if [walkProtypeChain] is set.
/// Tag types on function typed properties of [object] if [tagTypes] is set.
///
void addPropertiesFromSignature(
    sig, Set<NameValuePair> properties, object, bool walkPrototypeChain,
    {tagTypes: false}) {
  // Including these property names doesn't add any value and just clutters
  // the debugger output.
  // TODO(jacobr): consider adding runtimeType to this list.
  var skippedNames = new Set()..add('hashCode');

  while (sig != null) {
    for (var symbol in getOwnPropertySymbols(sig)) {
      var dartName = symbolName(symbol);
      String dartXPrefix = 'dartx.';
      if (dartName.startsWith(dartXPrefix)) {
        dartName = dartName.substring(dartXPrefix.length);
      }
      if (skippedNames.contains(dartName)) continue;
      var value = safeGetProperty(object, symbol);
      // Tag the function with its runtime type.
      if (tagTypes && _typeof(value) == 'function') {
        dart.tag(value, JS('', '#[#]', sig, symbol));
      }
      properties.add(new NameValuePair(name: dartName, value: value));
    }

    for (var name in getOwnPropertyNames(sig)) {
      var value = safeGetProperty(object, name);
      if (skippedNames.contains(name)) continue;
      // Tag the function with its runtime type.
      if (tagTypes && _typeof(value) == 'function') {
        dart.tag(value, JS('', '#[#]', sig, name));
      }
      properties.add(new NameValuePair(name: name, value: value));
    }

    if (!walkPrototypeChain) break;

    sig = safeGetProperty(sig, '__proto__');
  }
}

/// Sort properties sorting public names before private names.
List<NameValuePair> sortProperties(Iterable<NameValuePair> properties) {
  var sortedProperties = properties.toList();

  sortedProperties.sort((a, b) {
    var aPrivate = a.name.startsWith('_');
    var bPrivate = b.name.startsWith('_');
    if (aPrivate != bPrivate) return aPrivate ? 1 : -1;
    return a.name.compareTo(b.name);
  });
  return sortedProperties;
}

String getObjectTypeName(object) {
  var reifiedType = dart.getReifiedType(object);
  if (reifiedType == null) {
    if (_typeof(object) == 'function') {
      return '[[Raw JavaScript Function]]';
    }
    return '<Error getting type name>';
  }
  return getTypeName(reifiedType);
}

String getTypeName(type) {
  var name = dart.typeName(type);
  // Hack to cleanup names for List<dynamic>
  // TODO(jacobr): it would be nice if there was a way we could distinguish
  // between a List<dynamic> created from Dart and an Array passed in from
  // JavaScript.
  if (name == 'JSArray<dynamic>' || name == 'JSObject<Array>')
    return 'List<dynamic>';
  return name;
}

String safePreview(object, config) {
  try {
    var preview = _devtoolsFormatter._simpleFormatter.preview(object, config);
    if (preview != null) return preview;
    return object.toString();
  } catch (e) {
    return '<Exception thrown> $e';
  }
}

String symbolName(symbol) {
  var name = symbol.toString();
  assert(name.startsWith('Symbol('));
  return name.substring('Symbol('.length, name.length - 1);
}

bool hasMethod(object, String name) {
  try {
    return dart.hasMethod(object, name);
  } catch (e) {
    return false;
  }
}

/// [JsonMLFormatter] consumes [NameValuePair] objects and
class NameValuePair {
  NameValuePair(
      {this.name,
      this.value,
      this.config: JsonMLConfig.none,
      this.hideName: false});

  // Define equality and hashCode so that NameValuePair can be used
  // in a Set to dedupe entries with duplicate names.
  bool operator ==(other) {
    if (other is! NameValuePair) return false;
    if (this.hideName || other.hideName) return identical(this, other);
    return other.name == name;
  }

  int get hashCode => name.hashCode;

  final String name;
  final Object value;
  final JsonMLConfig config;
  final bool hideName;

  String get displayName => hideName ? '' : name;
}

class MapEntry {
  MapEntry({this.key, this.value});

  final Object key;
  final Object value;
}

class IterableSpan {
  IterableSpan(this.start, this.end, this.iterable);

  final int start;
  final int end;
  final Iterable iterable;
  int get length => end - start;

  /// Using length - .5, a list of length 10000 results in a
  /// maxPowerOfSubsetSize of 1, so the list will be broken up into 100,
  /// 100-length subsets. A list of length 10001 results in a
  /// maxPowerOfSubsetSize of 2, so the list will be broken up into 1
  /// 10000-length subset and 1 1-length subset.
  int get maxPowerOfSubsetSize =>
      (log(length - .5) / log(_maxSpanLength)).truncate();
  int get subsetSize => pow(_maxSpanLength, maxPowerOfSubsetSize);

  Map<int, dynamic> asMap() =>
      iterable.skip(start).take(length).toList().asMap();

  List<NameValuePair> children() {
    var children = <NameValuePair>[];
    if (length <= _maxSpanLength) {
      asMap().forEach((i, element) {
        children.add(
            new NameValuePair(name: (i + start).toString(), value: element));
      });
    } else {
      for (var i = start; i < end; i += subsetSize) {
        var subSpan = new IterableSpan(i, min(end, subsetSize + i), iterable);
        if (subSpan.length == 1) {
          children.add(new NameValuePair(
              name: i.toString(), value: iterable.elementAt(i)));
        } else {
          children.add(new NameValuePair(
              name: '[${i}...${subSpan.end - 1}]',
              value: subSpan,
              hideName: true));
        }
      }
    }
    return children;
  }
}

class Library {
  Library(this.name, this.object);

  final String name;
  final Object object;
}

class NamedConstructor {
  NamedConstructor(this.object);

  final Object object;
}

class HeritageClause {
  HeritageClause(this.name, this.types);

  final String name;
  final List types;
}

Object safeGetProperty(Object protoChain, Object name) {
  try {
    return JSNative.getProperty(protoChain, name);
  } catch (e) {
    return '<Exception thrown> $e';
  }
}

safeProperties(object) => new Map.fromIterable(
    getOwnPropertyNames(object)
        .where((each) => safeGetProperty(object, each) != null),
    key: (name) => name,
    value: (name) => safeGetProperty(object, name));

/// Class to simplify building the JsonML objects expected by the
/// Devtools Formatter API.
class JsonMLElement {
  dynamic _attributes;
  List _jsonML;

  JsonMLElement(tagName) {
    _attributes = JS('', '{}');
    _jsonML = [tagName, _attributes];
  }

  appendChild(element) {
    _jsonML.add(element.toJsonML());
  }

  JsonMLElement createChild(String tagName) {
    var c = new JsonMLElement(tagName);
    _jsonML.add(c.toJsonML());
    return c;
  }

  JsonMLElement createObjectTag(object) =>
      createChild('object')..addAttribute('object', object);

  void setStyle(String style) {
    _attributes.style = style;
  }

  addStyle(String style) {
    if (_attributes.style == null) {
      _attributes.style = style;
    } else {
      _attributes.style += style;
    }
  }

  addAttribute(key, value) {
    JSNative.setProperty(_attributes, key, value);
  }

  createTextChild(String text) {
    _jsonML.add(text);
  }

  toJsonML() => _jsonML;
}

/// Whether an object is a native JavaScript type where we should display the
/// JavaScript view of the object instead of the custom Dart specific render
/// of properties.
bool isNativeJavaScriptObject(object) {
  var type = _typeof(object);
  // Treat Node objects as a native JavaScript type as the regular DOM render
  // in devtools is superior to the dart specific view.
  return (type != 'object' && type != 'function') ||
      dart.isJsInterop(object) ||
      object is html.Node;
}

/// Class implementing the Devtools Formatter API described by:
/// https://docs.google.com/document/d/1FTascZXT9cxfetuPRT2eXPQKXui4nWFivUnS_335T3U
/// Specifically, a formatter implements a header, hasBody, and body method.
/// This class renders the simple structured format objects [_simpleFormatter]
/// provides as JsonML.
class JsonMLFormatter {
  // TODO(jacobr): define a SimpleFormatter base class that DartFormatter
  // implements if we decide to use this class elsewhere. We specify that the
  // type is DartFormatter here purely to get type checking benefits not because
  // this class is really intended to only support instances of type
  // DartFormatter.
  DartFormatter _simpleFormatter;

  bool customFormattersOn = false;

  JsonMLFormatter(this._simpleFormatter);

  void setMaxSpanLengthForTestingOnly(int spanLength) {
    _maxSpanLength = spanLength;
  }

  header(object, config) {
    customFormattersOn = true;
    if (config == JsonMLConfig.skipDart || isNativeJavaScriptObject(object)) {
      return null;
    }
    var c = _simpleFormatter.preview(object, config);
    if (c == null) return null;

    if (config == JsonMLConfig.keyToString) {
      c = object.toString();
    }

    // Indicate this is a Dart Object by using a Dart background color.
    // This is stylistically a bit ugly but it eases distinguishing Dart and
    // JS objects.
    var element = new JsonMLElement('span')
      ..setStyle('background-color: #d9edf7;')
      ..createTextChild(c);
    return element.toJsonML();
  }

  bool hasBody(object, config) => _simpleFormatter.hasChildren(object, config);

  body(object, config) {
    var body = new JsonMLElement('ol')
      ..setStyle('list-style-type: none;'
          'padding-left: 0px;'
          'margin-top: 0px;'
          'margin-bottom: 0px;'
          'margin-left: 12px;');
    if (object is StackTrace) {
      body.addStyle('color: rgb(196, 26, 22);');
    }
    var children = _simpleFormatter.children(object, config);
    if (children == null) return body.toJsonML();
    for (NameValuePair child in children) {
      var li = body.createChild('li');
      li.setStyle("padding-left: 13px;");

      // The value is indented when it is on a different line from the name
      // by setting right padding of the name to -13px and the padding of the
      // value to 13px.
      JsonMLElement nameSpan;
      var valueStyle = '';
      if (!child.hideName) {
        nameSpan = new JsonMLElement('span')
          ..createTextChild(
              child.displayName.isNotEmpty ? '${child.displayName}: ' : '')
          ..setStyle('color: rgb(136, 19, 145); margin-right: -13px');
        valueStyle = 'margin-left: 13px';
      }

      if (_typeof(child.value) == 'object' ||
          _typeof(child.value) == 'function') {
        var valueSpan = new JsonMLElement('span')..setStyle(valueStyle);
        valueSpan.createObjectTag(child.value)
          ..addAttribute('config', child.config);
        if (nameSpan != null) {
          li.appendChild(nameSpan);
        }
        li.appendChild(valueSpan);
      } else {
        var line = li.createChild('span');
        if (nameSpan != null) {
          line.appendChild(nameSpan);
        }
        line.appendChild(new JsonMLElement('span')
          ..createTextChild(safePreview(child.value, child.config))
          ..setStyle(valueStyle));
      }
    }
    return body.toJsonML();
  }
}

abstract class Formatter {
  bool accept(object, config);
  String preview(object);
  bool hasChildren(object);
  List<NameValuePair> children(object);
}

class DartFormatter {
  List<Formatter> _formatters;

  DartFormatter() {
    // The order of formatters matters as formatters earlier in the list take
    // precedence.
    _formatters = [
      new ClassFormatter(),
      new TypeFormatter(),
      new NamedConstructorFormatter(),
      new MapFormatter(),
      new IterableFormatter(),
      new IterableSpanFormatter(),
      new MapEntryFormatter(),
      new StackTraceFormatter(),
      new FunctionFormatter(),
      new HeritageClauseFormatter(),
      new LibraryModuleFormatter(),
      new LibraryFormatter(),
      new ObjectFormatter(),
    ];
  }

  String preview(object, config) {
    try {
      if (object == null ||
          object is num ||
          object is String ||
          isNativeJavaScriptObject(object)) {
        return object.toString();
      }
      for (var formatter in _formatters) {
        if (formatter.accept(object, config)) return formatter.preview(object);
      }
    } catch (e, trace) {
      // Log formatter internal errors as unfortunately the devtools cannot
      // be used to debug formatter errors.
      html.window.console.error("Caught exception $e\n trace:\n$trace");
    }

    return null;
  }

  bool hasChildren(object, config) {
    if (object == null) return false;
    try {
      for (var formatter in _formatters) {
        if (formatter.accept(object, config))
          return formatter.hasChildren(object);
      }
    } catch (e, trace) {
      // See comment for preview.
      html.window.console
          .error("[hasChildren] Caught exception $e\n trace:\n$trace");
    }
    return false;
  }

  List<NameValuePair> children(object, config) {
    try {
      if (object != null) {
        for (var formatter in _formatters) {
          if (formatter.accept(object, config))
            return formatter.children(object);
        }
      }
    } catch (e, trace) {
      // See comment for preview.
      html.window.console.error("Caught exception $e\n trace:\n$trace");
    }
    return <NameValuePair>[];
  }
}

/// Default formatter for Dart Objects.
class ObjectFormatter extends Formatter {
  bool accept(object, config) => !isNativeJavaScriptObject(object);

  String preview(object) => getObjectTypeName(object);

  bool hasChildren(object) => true;

  List<NameValuePair> children(object) {
    var type = dart.getType(object);
    var ret = new LinkedHashSet<NameValuePair>();
    // We use a Set rather than a List to avoid duplicates.
    var properties = new Set<NameValuePair>();
    addPropertiesFromSignature(
        dart.getFieldSig(type), properties, object, true);
    addPropertiesFromSignature(
        dart.getGetterSig(type), properties, object, true);
    ret.addAll(sortProperties(properties));
    addMetadataChildren(object, ret);
    return ret.toList();
  }
}

/// Formatter for module Dart Library objects.
class LibraryModuleFormatter implements Formatter {
  accept(object, config) => dart.getModuleName(object) != null;

  bool hasChildren(object) => true;

  String preview(object) {
    var libraryNames = dart.getModuleName(object).split('/');
    // Library names are received with a repeat directory name, so strip the
    // last directory entry here to make the path cleaner. For example, the
    // library "third_party/dart/utf/utf" shoud display as
    // "third_party/dart/utf/".
    if (libraryNames.length > 1 &&
        libraryNames.last == libraryNames[libraryNames.length - 2]) {
      libraryNames[libraryNames.length - 1] = '';
    }
    return 'Library Module: ${libraryNames.join('/')}';
  }

  List<NameValuePair> children(object) {
    var children = new LinkedHashSet<NameValuePair>();
    for (var name in getOwnPropertyNames(object)) {
      var value = safeGetProperty(object, name);
      children.add(new NameValuePair(
          name: name, value: new Library(name, value), hideName: true));
    }
    return children.toList();
  }
}

class LibraryFormatter implements Formatter {
  var genericParameters = new HashMap<String, String>();

  accept(object, config) => object is Library;

  bool hasChildren(object) => true;

  String preview(object) => object.name;

  List<NameValuePair> children(object) {
    // Maintain library member order rather than sorting members as is the
    // case for class members.
    var children = new LinkedHashSet<NameValuePair>();
    var objectProperties = safeProperties(object.object);
    objectProperties.forEach((name, value) {
      // Skip the generic constructors for each class as users are only
      // interested in seeing the actual classes.
      if (dart.getGenericTypeCtor(value) != null) return;

      children.add(dart.isType(value)
          ? classChild(name, value)
          : new NameValuePair(name: name, value: value));
    });
    return children.toList();
  }

  classChild(String name, Object child) {
    var typeName = getTypeName(child);
    return new NameValuePair(
        name: typeName, value: child, config: JsonMLConfig.asClass);
  }
}

/// Formatter for Dart Function objects.
/// 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 implements Formatter {
  accept(object, config) {
    if (_typeof(object) != 'function') return false;
    return dart.getReifiedType(object) != null;
  }

  bool hasChildren(object) => true;

  String preview(object) {
    return dart.typeName(dart.getReifiedType(object));
  }

  List<NameValuePair> children(object) => <NameValuePair>[
        new NameValuePair(name: 'signature', value: preview(object)),
        new NameValuePair(
            name: 'JavaScript Function',
            value: object,
            config: JsonMLConfig.skipDart)
      ];
}

/// Formatter for Dart Map objects.
class MapFormatter implements Formatter {
  accept(object, config) => object is Map;

  bool hasChildren(object) => true;

  String preview(object) {
    Map map = object;
    return '${getObjectTypeName(map)} length ${map.length}';
  }

  List<NameValuePair> children(object) {
    // TODO(jacobr): be lazier about enumerating contents of Maps that are not
    // the build in LinkedHashMap class.
    // TODO(jacobr): handle large Maps better.
    Map map = object;
    var entries = new LinkedHashSet<NameValuePair>();
    map.forEach((key, value) {
      var entryWrapper = new MapEntry(key: key, value: value);
      entries.add(new NameValuePair(
          name: entries.length.toString(), value: entryWrapper));
    });
    addMetadataChildren(object, entries);
    return entries.toList();
  }
}

/// Formatter for Dart Iterable objects including List and Set.
class IterableFormatter implements Formatter {
  bool accept(object, config) => object is Iterable;

  String preview(object) {
    Iterable iterable = object;
    try {
      var length = iterable.length;
      return '${getObjectTypeName(iterable)} length $length';
    } catch (_) {
      return '${getObjectTypeName(iterable)}';
    }
  }

  bool hasChildren(object) => true;

  List<NameValuePair> children(object) {
    // TODO(jacobr): be lazier about enumerating contents of Iterables that
    // are not the built in Set or List types.
    // TODO(jacobr): handle large Iterables better.
    // TODO(jacobr): consider only using numeric indices
    var children = new LinkedHashSet<NameValuePair>();
    children.addAll(new IterableSpan(0, object.length, object).children());
    // TODO(jacobr): provide a link to show regular class properties here.
    // required for subclasses of iterable, etc.
    addMetadataChildren(object, children);
    return children.toList();
  }
}

class NamedConstructorFormatter implements Formatter {
  accept(object, config) => object is NamedConstructor;

  // TODO(bmilligan): Display the signature of the named constructor as the
  // preview.
  String preview(object) => 'Named Constructor';

  bool hasChildren(object) => true;

  List<NameValuePair> children(object) => <NameValuePair>[
        new NameValuePair(
            name: 'JavaScript Function',
            value: object,
            config: JsonMLConfig.skipDart)
      ];
}

/// Formatter for synthetic MapEntry objects used to display contents of a Map
/// cleanly.
class MapEntryFormatter implements Formatter {
  accept(object, config) => object is MapEntry;

  String preview(object) {
    MapEntry entry = object;
    return '${safePreview(entry.key, JsonMLConfig.none)} => ${safePreview(entry.value, JsonMLConfig.none)}';
  }

  bool hasChildren(object) => true;

  List<NameValuePair> children(object) => <NameValuePair>[
        new NameValuePair(
            name: 'key', value: object.key, config: JsonMLConfig.keyToString),
        new NameValuePair(name: 'value', value: object.value)
      ];
}

/// Formatter for Dart Iterable objects including List and Set.
class HeritageClauseFormatter implements Formatter {
  bool accept(object, config) => object is HeritageClause;

  String preview(object) {
    HeritageClause clause = object;
    var typeNames = clause.types.map(getTypeName);
    return '${clause.name} ${typeNames.join(", ")}';
  }

  bool hasChildren(object) => true;

  List<NameValuePair> children(object) {
    HeritageClause clause = object;
    var children = <NameValuePair>[];
    for (var type in clause.types) {
      children
          .add(new NameValuePair(value: type, config: JsonMLConfig.asClass));
    }
    return children;
  }
}

/// Formatter for synthetic IterableSpan objects used to display contents of
/// an Iterable cleanly.
class IterableSpanFormatter implements Formatter {
  accept(object, config) => object is IterableSpan;

  String preview(object) {
    return '[${object.start}...${object.end-1}]';
  }

  bool hasChildren(object) => true;

  List<NameValuePair> children(object) => object.children();
}

class StackTraceFormatter implements Formatter {
  accept(object, config) => object is StackTrace;

  String preview(object) => 'StackTrace';

  bool hasChildren(object) => true;

  // Using the stack_trace formatting would be ideal, but adding the
  // dependency or re-writing the code is too messy, so each line of the
  // StackTrace will be added as its own child.
  List<NameValuePair> children(object) => object
      .toString()
      .split('\n')
      .map((line) => new NameValuePair(
          value: line.replaceFirst(new RegExp(r'^\s+at\s'), ''),
          hideName: true))
      .toList();
}

class ClassFormatter implements Formatter {
  accept(object, config) => config == JsonMLConfig.asClass;

  String preview(type) {
    var implements = dart.getImplements(type);
    var 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(type) {
    // TODO(jacobr): add other entries describing the class such as
    // implemented interfaces, and methods.
    var ret = new LinkedHashSet<NameValuePair>();

    var staticProperties = new Set<NameValuePair>();
    var staticMethods = new Set<NameValuePair>();
    // Static fields and properties.
    addPropertiesFromSignature(
        dart.getStaticFieldSig(type), staticProperties, type, false);
    addPropertiesFromSignature(
        dart.getStaticGetterSig(type), staticProperties, type, false);
    // static methods.
    addPropertiesFromSignature(
        dart.getStaticSig(type), staticMethods, type, false);

    if (staticProperties.isNotEmpty || staticMethods.isNotEmpty) {
      ret
        ..add(new NameValuePair(value: '[[Static members]]', hideName: true))
        ..addAll(sortProperties(staticProperties))
        ..addAll(sortProperties(staticMethods));
    }

    // instance methods.
    var instanceMethods = new Set<NameValuePair>();
    // Instance methods are defined on the prototype not the constructor object.
    addPropertiesFromSignature(dart.getMethodSig(type), instanceMethods,
        JS('', '#.prototype', type), false,
        tagTypes: true);
    if (instanceMethods.isNotEmpty) {
      ret
        ..add(new NameValuePair(value: '[[Instance Methods]]', hideName: true))
        ..addAll(sortProperties(instanceMethods));
    }

    var typeName = getTypeName(type);
    var mixins = dart.getMixins(type);
    if (mixins != null && mixins.isNotEmpty) {
      ret.add(new NameValuePair(
          name: '[[Mixins]]', value: new HeritageClause('mixins', mixins)));
    }

    var baseProto = JS('', '#.__proto__', type);
    if (baseProto != null && !dart.isJsInterop(baseProto)) {
      ret.add(new NameValuePair(
          name: "[[base class]]",
          value: baseProto,
          config: JsonMLConfig.asClass));
    }

    // TODO(jacobr): add back fields for named constructors.
    return ret.toList();
  }
}

class TypeFormatter implements Formatter {
  accept(object, config) => object is Type;

  String preview(object) => object.toString();

  bool hasChildren(object) => false;

  List<NameValuePair> children(object) => [];
}

typedef String StackTraceMapper(String stackTrace);

/// Hook for other parts of the SDK To use to map JS stack traces to Dart
/// stack traces.
///
/// Raw JS stack traces are used if $dartStackTraceUtility has not been
/// specified.
StackTraceMapper get stackTraceMapper {
  var _util = JS('', r'dart.global.$dartStackTraceUtility');
  return _util != null ? JS('StackTraceMapper', '#.mapper', _util) : null;
}

/// This entry point is automatically invoked by the code generated by
/// Dart Dev Compiler
registerDevtoolsFormatter() {
  var formatters = [_devtoolsFormatter];
  JS('', 'dart.global.devtoolsFormatters = #', formatters);
}

// Expose these methods here to facilitate writing debugger tests.
// If export worked for private SDK libraries we could just export
// these methods from dart:_runtime.

getModuleNames() {
  return dart.getModuleNames();
}

getModuleLibraries(String name) {
  return dart.getModuleLibraries(name);
}
