// 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;
    try {
      return '${getObjectTypeName(map)} length ${map.length}';
    } catch (e) {
      return safePreview(object, JsonMLConfig.none);
    }
  }

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