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

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

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

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

List<String> getOwnPropertyNames(object) =>
    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(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 = 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.fn(value, JS('', '#[#]', sig, symbol));
      }
      properties.add(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.fn(value, JS('', '#[#]', sig, name));
      }
      properties.add(NameValuePair(name: name, value: value));
    }

    if (!walkPrototypeChain) break;

    sig = dart.getPrototypeOf(sig);
  }
}

/// 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) {
  // 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.
  return dart.typeName(type);
}

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(NameValuePair(name: (i + start).toString(), value: element));
      });
    } else {
      for (var i = start; i < end; i += subsetSize) {
        var subSpan = IterableSpan(i, min(end, subsetSize + i), iterable);
        if (subSpan.length == 1) {
          children.add(
              NameValuePair(name: i.toString(), value: iterable.elementAt(i)));
        } else {
          children.add(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) => 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 = 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 = JsonMLElement('span')
      ..setStyle('background-color: #d9edf7;color: black')
      ..createTextChild(c);
    return element.toJsonML();
  }

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

  body(object, config) {
    var body = 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('background-color: thistle;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 = JsonMLElement('span')
          ..createTextChild(
              child.displayName.isNotEmpty ? '${child.displayName}: ' : '')
          ..setStyle(
              'background-color: thistle; color: rgb(136, 19, 145); margin-right: -13px');
        valueStyle = 'margin-left: 13px';
      }

      if (_typeof(child.value) == 'object' ||
          _typeof(child.value) == 'function') {
        var valueSpan = 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(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 = [
      ObjectInternalsFormatter(),
      ClassFormatter(),
      TypeFormatter(),
      NamedConstructorFormatter(),
      MapFormatter(),
      IterableFormatter(),
      IterableSpanFormatter(),
      MapEntryFormatter(),
      StackTraceFormatter(),
      ErrorAndExceptionFormatter(),
      FunctionFormatter(),
      HeritageClauseFormatter(),
      LibraryModuleFormatter(),
      LibraryFormatter(),
      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 = LinkedHashSet<NameValuePair>();
    // We use a Set rather than a List to avoid duplicates.
    var fields = Set<NameValuePair>();
    addPropertiesFromSignature(dart.getFields(type), fields, object, true);
    var getters = 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 = LinkedHashSet<NameValuePair>();
    for (var name in getOwnPropertyNames(object)) {
      var value = safeGetProperty(object, name);
      children.add(NameValuePair(
          name: name, value: Library(name, value), hideName: true));
    }
    return children.toList();
  }
}

class LibraryFormatter implements Formatter {
  var genericParameters = 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 = 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)
          : NameValuePair(name: name, value: value));
    });
    return children.toList();
  }

  classChild(String name, Object child) {
    var typeName = getTypeName(child);
    return 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>[
        NameValuePair(name: 'signature', value: preview(object)),
        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 = LinkedHashSet<NameValuePair>();
    map.forEach((key, value) {
      var entryWrapper = MapEntry(key: key, value: value);
      entries.add(
          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(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 = LinkedHashSet<NameValuePair>();
    children.addAll(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>[
        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>[
        NameValuePair(
            name: 'key', value: object.key, config: JsonMLConfig.keyToString),
        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(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();
}

/// Formatter for Dart Errors and Exceptions.
class ErrorAndExceptionFormatter extends ObjectFormatter {
  static final RegExp _pattern = RegExp(r'\d+\:\d+');

  accept(object, config) => object is Error || object is Exception;

  bool hasChildren(object) => true;

  String preview(object) {
    var trace = dart.stackTrace(object);
    // TODO(vsm): Pull our stack mapping logic here.  We should aim to
    // provide the first meaningful stack frame.
    var line = '$trace'.split('\n').firstWhere(
        (l) =>
            l.contains(_pattern) &&
            !l.contains('dart:sdk') &&
            !l.contains('dart_sdk'),
        orElse: () => null);
    return line != null ? '${object} at ${line}' : '${object}';
  }

  List<NameValuePair> children(object) {
    var trace = dart.stackTrace(object);
    var entries = LinkedHashSet<NameValuePair>();
    entries.add(NameValuePair(name: 'stackTrace', value: trace));
    addInstanceMembers(object, entries);
    addMetadataChildren(object, entries);
    return entries.toList();
  }

  // Add an ObjectFormatter view underneath.
  void addInstanceMembers(object, Set<NameValuePair> ret) {
    ret.add(NameValuePair(
        name: "[[instance members]]",
        value: object,
        config: JsonMLConfig.asObject));
  }
}

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) => NameValuePair(
          value: line.replaceFirst(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 = LinkedHashSet<NameValuePair>();

    var staticProperties = Set<NameValuePair>();
    var staticMethods = 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(NameValuePair(value: '[[Static members]]', hideName: true))
        ..addAll(sortProperties(staticProperties))
        ..addAll(sortProperties(staticMethods));
    }

    // instance methods.
    var instanceMethods = 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(NameValuePair(value: '[[Instance Methods]]', hideName: true))
        ..addAll(sortProperties(instanceMethods));
    }

    var mixin = dart.getMixin(type);
    if (mixin != null) {
      // TODO(jmesserly): this can only be one value.
      ret.add(NameValuePair(
          name: '[[Mixins]]', value: HeritageClause('mixins', [mixin])));
    }

    var baseProto = JS('', '#.__proto__', type);
    if (baseProto != null && !dart.isJsInterop(baseProto)) {
      ret.add(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'#.$dartStackTraceUtility', dart.global_);
  return _util != null ? JS('!', '#.mapper', _util) : null;
}

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

// These methods are exposed here for debugger tests.
//
// TODO(jmesserly): these are not exports because there is existing code that
// calls into them from JS. Currently `dartdevc` always resolves exports at
// compile time, so there is no need to make exports available at runtime by
// copying properties. For that reason we cannot use re-export.
//
// If these methods are only for tests, we should move them here, or change the
// tests to call the methods directly on dart:_runtime.
List<String> getModuleNames() => dart.getModuleNames();
getModuleLibraries(String name) => dart.getModuleLibraries(name);
