// 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:_interceptors' show JSArray;
import 'dart:_runtime' as dart;
import 'dart:core';
import 'dart:collection';
import 'dart:html' as html;
import 'dart:math';

part 'profile.dart';

/// 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");
  static const asObject = const JsonMLConfig("asObject");
  toString() => "JsonMLConfig($name)";
}

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

/// We truncate a toString() longer than [maxStringLength].
int maxFormatterStringLength = 100;

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

List<String> getOwnPropertyNames(object) =>
    new JSArray<String>.of(dart.getOwnPropertyNames(object));

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');
  var objectPrototype = JS('', 'Object.prototype');
  while (sig != null && !identical(sig, objectPrototype)) {
    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);
  if (type != 'object' && type != 'function') return true;

  // Consider all regular JS objects that do not represent Dart modules native
  // JavaScript objects.
  if (dart.isJsInterop(object) && dart.getModuleName(object) == null) {
    return true;
  }

  // Treat Node objects as a native JavaScript type as the regular DOM render
  // in devtools is superior to the dart specific view.
  return 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 ObjectInternalsFormatter(),
      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) {
    var typeName = getObjectTypeName(object);
    try {
      // An explicit toString() call might not actually be a string. This way
      // we're sure.
      var toString = "$object";
      if (toString.length > maxFormatterStringLength) {
        toString = toString.substring(0, maxFormatterStringLength - 3) + "...";
      }
      // The default toString() will be "Instance of 'Foo'", in which case we
      // don't need any further indication of the class.
      if (toString.contains(typeName)) {
        return toString;
      } else {
        // If there's no class indication, e.g. an Int64 that just prints as a
        // number, then add the class name.
        return "$toString ($typeName)";
      }
    } catch (e) {}
    // We will only get here if there was an error getting the toString, in
    // which case we just use the type name.
    return typeName;
  }

  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 fields = new Set<NameValuePair>();
    addPropertiesFromSignature(dart.getFields(type), fields, object, true);
    var getters = new Set<NameValuePair>();
    addPropertiesFromSignature(dart.getGetters(type), getters, object, true);
    ret.addAll(sortProperties(fields));
    ret.addAll(sortProperties(getters));
    addMetadataChildren(object, ret);
    return ret.toList();
  }
}

/// Show the object instance members and a reduced preview.
///
/// Used as a sub-entry to show the internals of objects that have a different
/// primary format. For example, a Map shows the key-value pairs, but this makes
/// the internals of the map visible for debugging.
class ObjectInternalsFormatter extends ObjectFormatter {
  bool accept(object, config) =>
      super.accept(object, config) && config == JsonMLConfig.asObject;

  // A minimal preview because we expect a full preview is already shown in a
  // parent formatter.
  String preview(object) {
    return getObjectTypeName(object);
  }
}

/// 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));
    });
    addInstanceMembers(object, entries);
    addMetadataChildren(object, entries);
    return entries.toList();
  }

  // We've formatted as a Map, but we may want to see the internals
  // of the Map, particularly for domain objects that implement Map.
  // Add an ObjectFormatter view underneath.
  void addInstanceMembers(object, Set<NameValuePair> ret) {
    ret.add(new NameValuePair(
        name: "[[instance members]]",
        value: object,
        config: JsonMLConfig.asObject));
  }
}

/// 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.getStaticFields(type), staticProperties, type, false);
    addPropertiesFromSignature(
        dart.getStaticGetters(type), staticProperties, type, false);
    // static methods.
    addPropertiesFromSignature(
        dart.getStaticMethods(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.getMethods(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 mixin = dart.getMixin(type);
    if (mixin != null) {
      // TODO(jmesserly): this can only be one value.
      ret.add(new NameValuePair(
          name: '[[Mixins]]', value: new HeritageClause('mixins', [mixin])));
    }

    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);
}
