// Copyright (c) 2013, 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._js_mirrors;

import 'dart:_js_embedded_names' show
    JsGetName,
    ALL_CLASSES,
    LAZIES,
    LIBRARIES,
    STATICS,
    TYPE_INFORMATION,
    TYPEDEF_PREDICATE_PROPERTY_NAME,
    TYPEDEF_TYPE_PROPERTY_NAME;

import 'dart:collection' show
    UnmodifiableListView,
    UnmodifiableMapView;

import 'dart:mirrors';

import 'dart:_foreign_helper' show
    JS,
    JS_GET_FLAG,
    JS_GET_STATIC_STATE,
    JS_CURRENT_ISOLATE_CONTEXT,
    JS_EMBEDDED_GLOBAL,
    JS_GET_NAME,
    JS_TYPEDEF_TAG,
    JS_FUNCTION_TYPE_RETURN_TYPE_TAG,
    JS_FUNCTION_TYPE_VOID_RETURN_TAG,
    JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG,
    JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG,
    JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG;


import 'dart:_internal' as _symbol_dev;

import 'dart:_js_helper' show
    BoundClosure,
    CachedInvocation,
    Closure,
    JSInvocationMirror,
    JsCache,
    Null,
    Primitives,
    ReflectionInfo,
    RuntimeError,
    TearOffClosure,
    TypeVariable,
    UnimplementedNoSuchMethodError,
    createRuntimeType,
    createUnmangledInvocationMirror,
    getMangledTypeName,
    getMetadata,
    getType,
    getRuntimeType,
    isDartFunctionType,
    runtimeTypeToString,
    setRuntimeTypeInfo,
    throwInvalidReflectionError,
    TypeImpl,
    deferredLoadHook;

import 'dart:_interceptors' show
    Interceptor,
    JSArray,
    JSExtendableArray,
    getInterceptor;

import 'dart:_js_names';

const String METHODS_WITH_OPTIONAL_ARGUMENTS = r'$methodsWithOptionalArguments';

bool hasReflectableProperty(var jsFunction) {
  return JS('bool', '# in #', JS_GET_NAME(JsGetName.REFLECTABLE), jsFunction);
}

/// No-op method that is called to inform the compiler that tree-shaking needs
/// to be disabled.
disableTreeShaking() => preserveNames();

/// No-op method that is called to inform the compiler that metadata must be
/// preserved at runtime.
preserveMetadata() {}

/// No-op method that is called to inform the compiler that the compiler must
/// preserve the URIs.
preserveUris() {}

/// No-op method that is called to inform the compiler that the compiler must
/// preserve the library names.
preserveLibraryNames() {}

String getName(Symbol symbol) {
  preserveNames();
  return n(symbol);
}

class JsMirrorSystem implements MirrorSystem {
  UnmodifiableMapView<Uri, LibraryMirror> _cachedLibraries;

  final IsolateMirror isolate = new JsIsolateMirror();

  JsTypeMirror get dynamicType => _dynamicType;
  JsTypeMirror get voidType => _voidType;

  static final JsTypeMirror _dynamicType =
      new JsTypeMirror(const Symbol('dynamic'));
  static final JsTypeMirror _voidType = new JsTypeMirror(const Symbol('void'));

  static Map<String, List<LibraryMirror>> _librariesByName;

  // Will be set to `true` when we have installed a hook on [deferredLoadHook]
  // to avoid installing it multiple times.
  static bool _hasInstalledDeferredLoadHook = false;

  static Map<String, List<LibraryMirror>> get librariesByName {
    if (_librariesByName == null) {
      _librariesByName = computeLibrariesByName();
      if (!_hasInstalledDeferredLoadHook) {
        _hasInstalledDeferredLoadHook = true;
        // After a deferred import has been loaded new libraries might have
        // been created, so in the hook we erase _librariesByName, so it will be
        // recomputed on the next access.
        deferredLoadHook = () => _librariesByName = null;
      }
    }
    return _librariesByName;
  }

  Map<Uri, LibraryMirror> get libraries {
    if (_cachedLibraries != null) return _cachedLibraries;
    Map<Uri, LibraryMirror> result = new Map();
    for (List<LibraryMirror> list in librariesByName.values) {
      for (LibraryMirror library in list) {
        result[library.uri] = library;
      }
    }
    return _cachedLibraries =
        new UnmodifiableMapView<Uri, LibraryMirror>(result);
  }

  LibraryMirror findLibrary(Symbol libraryName) {
    return librariesByName[n(libraryName)].single;
  }

  static Map<String, List<LibraryMirror>> computeLibrariesByName() {
    disableTreeShaking();
    var result = new Map<String, List<LibraryMirror>>();
    var jsLibraries = JS_EMBEDDED_GLOBAL('JSExtendableArray|Null', LIBRARIES);
    if (jsLibraries == null) return result;
    for (List data in jsLibraries) {
      String name = data[0];
      String uriString = data[1];
      Uri uri;
      // The Uri has been compiled out. Create a URI from the simple name.
      if (uriString != "") {
        uri = Uri.parse(uriString);
      } else {
        uri = new Uri(scheme: 'https',
                      host: 'dartlang.org',
                      path: 'dart2js-stripped-uri',
                      queryParameters: { 'lib': name });
      }
      List<String> classes = data[2];
      List<String> functions = data[3];
      var metadataFunction = data[4];
      var fields = data[5];
      bool isRoot = data[6];
      var globalObject = data[7];
      List metadata = (metadataFunction == null)
          ? const [] : JS('List', '#()', metadataFunction);
      var libraries = result.putIfAbsent(name, () => <LibraryMirror>[]);
      libraries.add(
          new JsLibraryMirror(
              s(name), uri, classes, functions, metadata, fields, isRoot,
              globalObject));
    }
    return result;
  }
}

abstract class JsMirror implements Mirror {
  const JsMirror();

  String get _prettyName;

  String toString() => _prettyName;

  // TODO(ahe): Remove this method from the API.
  MirrorSystem get mirrors => currentJsMirrorSystem;

  _getField(JsMirror receiver) {
    throw new UnimplementedError();
  }

  void _setField(JsMirror receiver, Object arg) {
    throw new UnimplementedError();
  }

  _loadField(String name) {
    throw new UnimplementedError();
  }

  void _storeField(String name, Object arg) {
    throw new UnimplementedError();
  }
}

// This class is somewhat silly in the current implementation.
class JsIsolateMirror extends JsMirror implements IsolateMirror {
  final _isolateContext = JS_CURRENT_ISOLATE_CONTEXT();

  String get _prettyName => 'Isolate';

  String get debugName {
    String id = _isolateContext == null ? 'X' : _isolateContext.id.toString();
    // Using name similar to what the VM uses.
    return '${n(rootLibrary.simpleName)}-$id';
  }

  bool get isCurrent => JS_CURRENT_ISOLATE_CONTEXT() == _isolateContext;

  LibraryMirror get rootLibrary {
    return currentJsMirrorSystem.libraries.values.firstWhere(
        (JsLibraryMirror library) => library._isRoot);
  }
}

abstract class JsDeclarationMirror extends JsMirror
    implements DeclarationMirror {
  final Symbol simpleName;

  const JsDeclarationMirror(this.simpleName);

  Symbol get qualifiedName => computeQualifiedName(owner, simpleName);

  bool get isPrivate => n(simpleName).startsWith('_');

  bool get isTopLevel => owner != null && owner is LibraryMirror;

  // TODO(ahe): This should use qualifiedName.
  String toString() => "$_prettyName on '${n(simpleName)}'";

  List<JsMethodMirror> get _methods {
    throw new RuntimeError('Should not call _methods');
  }

  _invoke(List positionalArguments, Map<Symbol, dynamic> namedArguments) {
    throw new RuntimeError('Should not call _invoke');
  }

  // TODO(ahe): Implement this.
  SourceLocation get location => throw new UnimplementedError();
}

class JsTypeVariableMirror extends JsTypeMirror implements TypeVariableMirror {
  final DeclarationMirror owner;
  final TypeVariable _typeVariable;
  final int _metadataIndex;
  TypeMirror _cachedUpperBound;

  JsTypeVariableMirror(TypeVariable typeVariable, this.owner,
                       this._metadataIndex)
      : this._typeVariable = typeVariable,
        super(s(typeVariable.name));

  bool operator ==(other) {
    return (other is JsTypeVariableMirror &&
        simpleName == other.simpleName &&
        owner == other.owner);
  }

  int get hashCode {
    int code = 0x3FFFFFFF & (JsTypeVariableMirror).hashCode;
    code ^= 17 * simpleName.hashCode;
    code ^= 19 * owner.hashCode;
    return code;
  }

  String get _prettyName => 'TypeVariableMirror';

  bool get isTopLevel => false;
  bool get isStatic => false;

  TypeMirror get upperBound {
    if (_cachedUpperBound != null) return _cachedUpperBound;
    return _cachedUpperBound = typeMirrorFromRuntimeTypeRepresentation(
        owner, getType(_typeVariable.bound));
  }

  bool isSubtypeOf(TypeMirror other) => throw new UnimplementedError();
  bool isAssignableTo(TypeMirror other) => throw new UnimplementedError();

  _asRuntimeType() => _metadataIndex;
}

class JsTypeMirror extends JsDeclarationMirror implements TypeMirror {
  JsTypeMirror(Symbol simpleName)
      : super(simpleName);

  String get _prettyName => 'TypeMirror';

  DeclarationMirror get owner => null;

  // TODO(ahe): Doesn't match the specification, see http://dartbug.com/11569.
  bool get isTopLevel => true;

  // TODO(ahe): Implement these.
  List<InstanceMirror> get metadata => throw new UnimplementedError();

  bool get hasReflectedType => false;
  Type get reflectedType {
    throw new UnsupportedError("This type does not support reflectedType");
  }

  List<TypeVariableMirror> get typeVariables => const <TypeVariableMirror>[];
  List<TypeMirror> get typeArguments => const <TypeMirror>[];

  bool get isOriginalDeclaration => true;
  TypeMirror get originalDeclaration => this;

  bool isSubtypeOf(TypeMirror other) => throw new UnimplementedError();
  bool isAssignableTo(TypeMirror other) => throw new UnimplementedError();

  _asRuntimeType() {
    if (this == JsMirrorSystem._dynamicType) return null;
    if (this == JsMirrorSystem._voidType) return null;
    throw new RuntimeError('Should not call _asRuntimeType');
  }
}

class JsLibraryMirror extends JsDeclarationMirror with JsObjectMirror
    implements LibraryMirror {
  final Uri _uri;
  final List<String> _classes;
  final List<String> _functions;
  final List _metadata;
  final String _compactFieldSpecification;
  final bool _isRoot;
  final _globalObject;
  List<JsMethodMirror> _cachedFunctionMirrors;
  List<VariableMirror> _cachedFields;
  UnmodifiableMapView<Symbol, ClassMirror> _cachedClasses;
  UnmodifiableMapView<Symbol, MethodMirror> _cachedFunctions;
  UnmodifiableMapView<Symbol, MethodMirror> _cachedGetters;
  UnmodifiableMapView<Symbol, MethodMirror> _cachedSetters;
  UnmodifiableMapView<Symbol, VariableMirror> _cachedVariables;
  UnmodifiableMapView<Symbol, Mirror> _cachedMembers;
  UnmodifiableMapView<Symbol, DeclarationMirror> _cachedDeclarations;
  UnmodifiableListView<InstanceMirror> _cachedMetadata;

  JsLibraryMirror(Symbol simpleName,
                  this._uri,
                  this._classes,
                  this._functions,
                  this._metadata,
                  this._compactFieldSpecification,
                  this._isRoot,
                  this._globalObject)
      : super(simpleName) {
    preserveLibraryNames();
  }

  String get _prettyName => 'LibraryMirror';

  Uri get uri {
    preserveUris();
    return _uri;
  }

  Symbol get qualifiedName => simpleName;

  List<JsMethodMirror> get _methods => _functionMirrors;

  Map<Symbol, ClassMirror> get __classes {
    if (_cachedClasses != null) return _cachedClasses;
    var result = new Map();
    for (String className in _classes) {
      var cls = reflectClassByMangledName(className);
      if (cls is ClassMirror) {
        cls = cls.originalDeclaration;
      }
      if (cls is JsClassMirror) {
        result[cls.simpleName] = cls;
        cls._owner = this;
      } else  if (cls is JsTypedefMirror) {
        result[cls.simpleName] = cls;
      }
    }
    return _cachedClasses =
        new UnmodifiableMapView<Symbol, ClassMirror>(result);
  }

  InstanceMirror setField(Symbol fieldName, Object arg) {
    String name = n(fieldName);
    if (name.endsWith('=')) throw new ArgumentError('');
    var mirror = __functions[s('$name=')];
    if (mirror == null) mirror = __variables[fieldName];
    if (mirror == null) {
      throw new NoSuchStaticMethodError.method(
          null, setterSymbol(fieldName), [arg], null);
    }
    mirror._setField(this, arg);
    return reflect(arg);
  }

  InstanceMirror getField(Symbol fieldName) {
    JsMirror mirror = __members[fieldName];
    if (mirror == null) {
      throw new NoSuchStaticMethodError.method(null, fieldName, [], null);
    }
    if (mirror is! MethodMirror) return reflect(mirror._getField(this));
    JsMethodMirror methodMirror = mirror;
    if (methodMirror.isGetter) return reflect(mirror._getField(this));
    assert(methodMirror.isRegularMethod);
    var getter = JS("", "#['\$getter']", methodMirror._jsFunction);
    if (getter == null) throw new UnimplementedError();
    return reflect(JS("", "#()", getter));
  }

  InstanceMirror invoke(Symbol memberName,
                        List positionalArguments,
                        [Map<Symbol, dynamic> namedArguments]) {
    if (namedArguments != null && !namedArguments.isEmpty) {
      throw new UnsupportedError('Named arguments are not implemented.');
    }
    JsDeclarationMirror mirror = __members[memberName];

    if (mirror is JsMethodMirror && !mirror.canInvokeReflectively()) {
      throwInvalidReflectionError(n(memberName));
    }
    if (mirror == null || mirror is JsMethodMirror && mirror.isSetter) {
      throw new NoSuchStaticMethodError.method(
          null, memberName, positionalArguments, namedArguments);
    }
    if (mirror is JsMethodMirror && !mirror.isGetter) {
      return reflect(mirror._invoke(positionalArguments, namedArguments));
    }
    return getField(memberName)
        .invoke(#call, positionalArguments, namedArguments);
  }

  _loadField(String name) {
    // TODO(ahe): What about lazily initialized fields? See
    // [JsClassMirror.getField].

    // '$' (JS_GET_STATIC_STATE()) stores state which is read directly, so we
    // shouldn't use [_globalObject] here.
    assert(JS('bool', '# in #', name, JS_GET_STATIC_STATE()));
    return JS('', '#[#]', JS_GET_STATIC_STATE(), name);
  }

  void _storeField(String name, Object arg) {
    // '$' (JS_GET_STATIC_STATE()) stores state which is stored directly, so we
    // shouldn't use [_globalObject] here.
    assert(JS('bool', '# in #', name, JS_GET_STATIC_STATE()));
    JS('void', '#[#] = #', JS_GET_STATIC_STATE(), name, arg);
  }

  List<JsMethodMirror> get _functionMirrors {
    if (_cachedFunctionMirrors != null) return _cachedFunctionMirrors;
    var result = new List<JsMethodMirror>();
    for (int i = 0; i < _functions.length; i++) {
      String name = _functions[i];
      var jsFunction = JS('', '#[#]', _globalObject, name);
      String unmangledName = mangledGlobalNames[name];
      if (unmangledName == null ||
          JS('bool', "!!#['\$getterStub']", jsFunction)) {
        // If there is no unmangledName, [jsFunction] is either a synthetic
        // implementation detail, or something that is excluded
        // by @MirrorsUsed.
        // If it has a getterStub property it is a synthetic stub.
        // TODO(floitsch): Remove the getterStub hack.
        continue;
      }
      bool isConstructor = unmangledName.startsWith('new ');
      bool isStatic = !isConstructor; // Top-level functions are static, but
                                      // constructors are not.
      if (isConstructor) {
        unmangledName = unmangledName.substring(4).replaceAll(r'$', '.');
      }
      JsMethodMirror mirror =
          new JsMethodMirror.fromUnmangledName(
              unmangledName, jsFunction, isStatic, isConstructor);
      result.add(mirror);
      mirror._owner = this;
    }
    return _cachedFunctionMirrors = result;
  }

  List<VariableMirror> get _fields {
    if (_cachedFields != null) return _cachedFields;
    var result = <VariableMirror>[];
    parseCompactFieldSpecification(
        this, _compactFieldSpecification, true, result);
    return _cachedFields = result;
  }

  Map<Symbol, MethodMirror> get __functions {
    if (_cachedFunctions != null) return _cachedFunctions;
    var result = new Map();
    for (JsMethodMirror mirror in _functionMirrors) {
      if (!mirror.isConstructor) result[mirror.simpleName] = mirror;
    }
    return _cachedFunctions =
        new UnmodifiableMapView<Symbol, MethodMirror>(result);
  }

  Map<Symbol, MethodMirror> get __getters {
    if (_cachedGetters != null) return _cachedGetters;
    var result = new Map();
    // TODO(ahe): Implement this.
    return _cachedGetters =
        new UnmodifiableMapView<Symbol, MethodMirror>(result);
  }

  Map<Symbol, MethodMirror> get __setters {
    if (_cachedSetters != null) return _cachedSetters;
    var result = new Map();
    // TODO(ahe): Implement this.
    return _cachedSetters =
        new UnmodifiableMapView<Symbol, MethodMirror>(result);
  }

  Map<Symbol, VariableMirror> get __variables {
    if (_cachedVariables != null) return _cachedVariables;
    var result = new Map();
    for (JsVariableMirror mirror in _fields) {
      result[mirror.simpleName] = mirror;
    }
    return _cachedVariables =
        new UnmodifiableMapView<Symbol, VariableMirror>(result);
  }

  Map<Symbol, Mirror> get __members {
    if (_cachedMembers !=  null) return _cachedMembers;
    Map<Symbol, Mirror> result = new Map.from(__classes);
    addToResult(Symbol key, Mirror value) {
      result[key] = value;
    }
    __functions.forEach(addToResult);
    __getters.forEach(addToResult);
    __setters.forEach(addToResult);
    __variables.forEach(addToResult);
    return _cachedMembers = new UnmodifiableMapView<Symbol, Mirror>(result);
  }

  Map<Symbol, DeclarationMirror> get declarations {
    if (_cachedDeclarations != null) return _cachedDeclarations;
    var result = new Map<Symbol, DeclarationMirror>();
    addToResult(Symbol key, Mirror value) {
      result[key] = value;
    }
    __members.forEach(addToResult);
    return _cachedDeclarations =
        new UnmodifiableMapView<Symbol, DeclarationMirror>(result);
  }

  List<InstanceMirror> get metadata {
    if (_cachedMetadata != null) return _cachedMetadata;
    preserveMetadata();
    return _cachedMetadata =
        new UnmodifiableListView<InstanceMirror>(_metadata.map(reflect));
  }

  // TODO(ahe): Test this getter.
  DeclarationMirror get owner => null;

  List<LibraryDependencyMirror> get libraryDependencies
      => throw new UnimplementedError();
}

String n(Symbol symbol) => _symbol_dev.Symbol.getName(symbol);

Symbol s(String name) {
  if (name == null) return null;
  return new _symbol_dev.Symbol.unvalidated(name);
}

Symbol setterSymbol(Symbol symbol) => s("${n(symbol)}=");

final JsMirrorSystem currentJsMirrorSystem = new JsMirrorSystem();

InstanceMirror reflect(Object reflectee) {
  if (reflectee is Closure) {
    return new JsClosureMirror(reflectee);
  } else {
    return new JsInstanceMirror(reflectee);
  }
}

TypeMirror reflectType(Type key) {
  return reflectClassByMangledName(getMangledTypeName(key));
}

TypeMirror reflectClassByMangledName(String mangledName) {
  String unmangledName = mangledGlobalNames[mangledName];
  if (mangledName == 'dynamic') return JsMirrorSystem._dynamicType;
  if (mangledName == 'void') return JsMirrorSystem._voidType;
  if (unmangledName == null) unmangledName = mangledName;
  return reflectClassByName(s(unmangledName), mangledName);
}

var classMirrors;

TypeMirror reflectClassByName(Symbol symbol, String mangledName) {
  if (classMirrors == null) classMirrors = JsCache.allocate();
  var mirror = JsCache.fetch(classMirrors, mangledName);
  if (mirror != null) return mirror;
  disableTreeShaking();
  int typeArgIndex = mangledName.indexOf("<");
  if (typeArgIndex != -1) {
    TypeMirror originalDeclaration =
        reflectClassByMangledName(mangledName.substring(0, typeArgIndex))
        .originalDeclaration;
    if (originalDeclaration is JsTypedefMirror) {
      throw new UnimplementedError();
    }
    mirror = new JsTypeBoundClassMirror(originalDeclaration,
        // Remove the angle brackets enclosing the type arguments.
        mangledName.substring(typeArgIndex + 1, mangledName.length - 1));
    JsCache.update(classMirrors, mangledName, mirror);
    return mirror;
  }
  var allClasses = JS_EMBEDDED_GLOBAL('', ALL_CLASSES);
  var constructor = JS('var', '#[#]', allClasses, mangledName);
  if (constructor == null) {
    // Probably an intercepted class.
    // TODO(ahe): How to handle intercepted classes?
    throw new UnsupportedError('Cannot find class for: ${n(symbol)}');
  }
  var descriptor = JS('', '#["@"]', constructor);
  var fields;
  var fieldsMetadata;
  if (descriptor == null) {
    // This is a native class, or an intercepted class.
    // TODO(ahe): Preserve descriptor for such classes.
  } else if (JS('bool', '# in #',
                TYPEDEF_PREDICATE_PROPERTY_NAME, descriptor)) {
    // Typedefs are represented as normal classes with two special properties:
    //   TYPEDEF_PREDICATE_PROPERTY_NAME and TYPEDEF_TYPE_PROPERTY_NAME.
    // For example:
    //  MyTypedef: {
    //     "^": "Object;",
    //     $typedefType: 58,
    //     $$isTypedef: true
    //  }
    //  The typedefType is the index into the metadata table.
    int index = JS('int', '#[#]', descriptor, TYPEDEF_TYPE_PROPERTY_NAME);
    mirror = new JsTypedefMirror(symbol, mangledName, getType(index));
  } else {
    fields = JS('', '#[#]', descriptor,
        JS_GET_NAME(JsGetName.CLASS_DESCRIPTOR_PROPERTY));
    if (fields is List) {
      fieldsMetadata = fields.getRange(1, fields.length).toList();
      fields = fields[0];
    }
    if (fields is! String) {
      // TODO(ahe): This is CSP mode.  Find a way to determine the
      // fields of this class.
      fields = '';
    }
  }

  if (mirror == null) {
    var superclassName = fields.split(';')[0];
    var mixins = superclassName.split('+');
    if (mixins.length > 1 && mangledGlobalNames[mangledName] == null) {
      mirror = reflectMixinApplication(mixins, mangledName);
    } else {
      ClassMirror classMirror = new JsClassMirror(
          symbol, mangledName, constructor, fields, fieldsMetadata);
      List typeVariables =
          JS('JSExtendableArray|Null', '#.prototype["<>"]', constructor);
      if (typeVariables == null || typeVariables.length == 0) {
        mirror = classMirror;
      } else {
        String typeArguments = 'dynamic';
        for (int i = 1; i < typeVariables.length; i++) {
          typeArguments += ',dynamic';
        }
        mirror = new JsTypeBoundClassMirror(classMirror, typeArguments);
      }
    }
  }

  JsCache.update(classMirrors, mangledName, mirror);
  return mirror;
}

Map<Symbol, MethodMirror> filterMethods(List<MethodMirror> methods) {
  var result = new Map();
  for (JsMethodMirror method in methods) {
    if (!method.isConstructor && !method.isGetter && !method.isSetter) {
      result[method.simpleName] = method;
    }
  }
  return result;
}

Map<Symbol, MethodMirror> filterConstructors(methods) {
  var result = new Map();
  for (JsMethodMirror method in methods) {
    if (method.isConstructor) {
      result[method.simpleName] = method;
    }
  }
  return result;
}

Map<Symbol, MethodMirror> filterGetters(List<MethodMirror> methods,
                                        Map<Symbol, VariableMirror> fields) {
  var result = new Map();
  for (JsMethodMirror method in methods) {
    if (method.isGetter) {

      // TODO(ahe): This is a hack to remove getters corresponding to a field.
      if (fields[method.simpleName] != null) continue;

      result[method.simpleName] = method;
    }
  }
  return result;
}

Map<Symbol, MethodMirror> filterSetters(List<MethodMirror> methods,
                                        Map<Symbol, VariableMirror> fields) {
  var result = new Map();
  for (JsMethodMirror method in methods) {
    if (method.isSetter) {

      // TODO(ahe): This is a hack to remove setters corresponding to a field.
      String name = n(method.simpleName);
      name = name.substring(0, name.length - 1); // Remove '='.
      if (fields[s(name)] != null) continue;

      result[method.simpleName] = method;
    }
  }
  return result;
}

Map<Symbol, Mirror> filterMembers(List<MethodMirror> methods,
                                  Map<Symbol, VariableMirror> variables) {
  Map<Symbol, Mirror> result = new Map.from(variables);
  for (JsMethodMirror method in methods) {
    if (method.isSetter) {
      String name = n(method.simpleName);
      name = name.substring(0, name.length - 1);
      // Filter-out setters corresponding to variables.
      if (result[s(name)] is VariableMirror) continue;
    }
    // Constructors aren't 'members'.
    if (method.isConstructor) continue;
    // Filter out synthetic tear-off stubs
    if (JS('bool', r'!!#.$getterStub', method._jsFunction)) continue;
    // Use putIfAbsent to filter-out getters corresponding to variables.
    result.putIfAbsent(method.simpleName, () => method);
  }
  return result;
}

int counter = 0;

ClassMirror reflectMixinApplication(mixinNames, String mangledName) {
  disableTreeShaking();
  var mixins = [];
  for (String mangledName in mixinNames) {
    mixins.add(reflectClassByMangledName(mangledName));
  }
  var it = mixins.iterator;
  it.moveNext();
  var superclass = it.current;
  while (it.moveNext()) {
    superclass = new JsMixinApplication(superclass, it.current, mangledName);
  }
  return superclass;
}

class JsMixinApplication extends JsTypeMirror with JsObjectMirror
    implements ClassMirror {
  final ClassMirror superclass;
  final ClassMirror mixin;
  Symbol _cachedSimpleName;
  Map<Symbol, MethodMirror> _cachedInstanceMembers;

  JsMixinApplication(ClassMirror superclass, ClassMirror mixin,
                     String mangledName)
      : this.superclass = superclass,
        this.mixin = mixin,
        super(s(mangledName));

  String get _prettyName => 'ClassMirror';

  Symbol get simpleName {
    if (_cachedSimpleName != null) return _cachedSimpleName;
    String superName = n(superclass.qualifiedName);
    return _cachedSimpleName = (superName.contains(' with '))
        ? s('$superName, ${n(mixin.qualifiedName)}')
        : s('$superName with ${n(mixin.qualifiedName)}');
  }

  Symbol get qualifiedName => simpleName;

  // TODO(ahe): Remove this method, only here to silence warning.
  get _mixin => mixin;

  Map<Symbol, Mirror> get __members => _mixin.__members;

  Map<Symbol, MethodMirror> get __methods => _mixin.__methods;

  Map<Symbol, MethodMirror> get __getters => _mixin.__getters;

  Map<Symbol, MethodMirror> get __setters => _mixin.__setters;

  Map<Symbol, VariableMirror> get __variables => _mixin.__variables;

  Map<Symbol, DeclarationMirror> get declarations => mixin.declarations;

  Map<Symbol, MethodMirror> get instanceMembers {
    if (_cachedInstanceMembers == null) {
      var result = new Map<Symbol, MethodMirror>();
      if (superclass != null) {
        result.addAll(superclass.instanceMembers);
      }
      result.addAll(mixin.instanceMembers);
      _cachedInstanceMembers = result;
    }
    return _cachedInstanceMembers;
  }

  Map<Symbol, MethodMirror> get staticMembers => mixin.staticMembers;

  _asRuntimeType() => null;

  InstanceMirror invoke(
      Symbol memberName,
      List positionalArguments,
      [Map<Symbol,dynamic> namedArguments]) {
    throw new NoSuchStaticMethodError.method(
        null, memberName, positionalArguments, namedArguments);
  }

  InstanceMirror getField(Symbol fieldName) {
    throw new NoSuchStaticMethodError.method(null, fieldName, null, null);
  }

  InstanceMirror setField(Symbol fieldName, Object arg) {
    throw new NoSuchStaticMethodError.method(
        null, setterSymbol(fieldName), [arg], null);
  }

  List<ClassMirror> get superinterfaces => [mixin];

  Map<Symbol, MethodMirror> get __constructors => _mixin.__constructors;

  InstanceMirror newInstance(
      Symbol constructorName,
      List positionalArguments,
      [Map<Symbol,dynamic> namedArguments]) {
    throw new UnsupportedError(
        "Can't instantiate mixin application '${n(qualifiedName)}'");
  }

  bool get isOriginalDeclaration => true;

  ClassMirror get originalDeclaration => this;

  // TODO(ahe): Implement this.
  List<TypeVariableMirror> get typeVariables {
    throw new UnimplementedError();
  }

  List<TypeMirror> get typeArguments => const <TypeMirror>[];

  bool get isAbstract => throw new UnimplementedError();

  bool get isEnum => throw new UnimplementedError();

  bool isSubclassOf(ClassMirror other) {
    superclass.isSubclassOf(other) || mixin.isSubclassOf(other);
  }

  bool isSubtypeOf(TypeMirror other) => throw new UnimplementedError();

  bool isAssignableTo(TypeMirror other) => throw new UnimplementedError();
}

abstract class JsObjectMirror implements ObjectMirror {
}

class JsInstanceMirror extends JsObjectMirror implements InstanceMirror {
  final reflectee;

  JsInstanceMirror(this.reflectee);

  bool get hasReflectee => true;

  ClassMirror get type {
    // The spec guarantees that `null` is the singleton instance of the `Null`
    // class.
    if (reflectee == null) return reflectClass(Null);
    return reflectType(getRuntimeType(reflectee));
  }

  InstanceMirror invoke(Symbol memberName,
                        List positionalArguments,
                        [Map<Symbol,dynamic> namedArguments]) {
    if (namedArguments == null) namedArguments = const {};
    // We can safely pass positionalArguments to _invoke as it will wrap it in
    // a JSArray if needed.
    return _invoke(memberName, JSInvocationMirror.METHOD,
                   positionalArguments, namedArguments);
  }

  InstanceMirror _invokeMethodWithNamedArguments(
      String reflectiveName,
      List positionalArguments, Map<Symbol,dynamic> namedArguments) {
    assert(namedArguments.isNotEmpty);
    var interceptor = getInterceptor(reflectee);

    var jsFunction = JS('', '#[#]', interceptor, reflectiveName);
    if (jsFunction == null) {
      // TODO(ahe): Invoke noSuchMethod.
      throw new UnimplementedNoSuchMethodError(
          'Invoking noSuchMethod with named arguments not implemented');
    }
    ReflectionInfo info = new ReflectionInfo(jsFunction);
    if (jsFunction == null) {
      // TODO(ahe): Invoke noSuchMethod.
      throw new UnimplementedNoSuchMethodError(
          'Invoking noSuchMethod with named arguments not implemented');
    }

    positionalArguments = new List.from(positionalArguments);
    // Check the number of positional arguments is valid.
    if (info.requiredParameterCount != positionalArguments.length) {
      // TODO(ahe): Invoke noSuchMethod.
      throw new UnimplementedNoSuchMethodError(
          'Invoking noSuchMethod with named arguments not implemented');
    }
    var defaultArguments = new Map();
    for (int i = 0; i < info.optionalParameterCount; i++) {
      var parameterName = info.parameterName(i + info.requiredParameterCount);
      var defaultValue =
          getMetadata(info.defaultValue(i + info.requiredParameterCount));
      defaultArguments[parameterName] = defaultValue;
    }
    namedArguments.forEach((Symbol symbol, value) {
      String parameter = n(symbol);
      if (defaultArguments.containsKey(parameter)) {
        defaultArguments[parameter] = value;
      } else {
        // Extraneous named argument.
        // TODO(ahe): Invoke noSuchMethod.
        throw new UnimplementedNoSuchMethodError(
            'Invoking noSuchMethod with named arguments not implemented');
      }
    });
    positionalArguments.addAll(defaultArguments.values);
    // TODO(ahe): Handle intercepted methods.
    return reflect(
        JS('', '#.apply(#, #)', jsFunction, reflectee, positionalArguments));
  }

  /// Grabs hold of the class-specific invocation cache for the reflectee.
  /// All reflectees with the same class share the same cache. The cache
  /// maps reflective names to cached invocation objects with enough decoded
  /// reflective information to know how to to invoke a specific member.
  get _classInvocationCache {
    String cacheName = Primitives.mirrorInvokeCacheName;
    var cacheHolder = (reflectee == null) ? getInterceptor(null) : reflectee;
    var cache = JS('', r'#.constructor[#]', cacheHolder, cacheName);
    if (cache == null) {
      cache = JsCache.allocate();
      JS('void', r'#.constructor[#] = #', cacheHolder, cacheName, cache);
    }
    return cache;
  }

  String _computeReflectiveName(Symbol symbolName, int type,
                                List positionalArguments,
                                Map<Symbol, dynamic> namedArguments) {
    String name = n(symbolName);
    switch (type) {
      case JSInvocationMirror.GETTER: return name;
      case JSInvocationMirror.SETTER: return '$name=';
      case JSInvocationMirror.METHOD:
        if (namedArguments.isNotEmpty) return '$name*';
        int nbArgs = positionalArguments.length as int;
        return "$name:$nbArgs";
    }
    throw new RuntimeError("Could not compute reflective name for $name");
  }

  /**
   * Returns a `CachedInvocation` or `CachedNoSuchMethodInvocation` for the
   * given member.
   *
   * Caches the result.
   */
  _getCachedInvocation(Symbol name, int type, String reflectiveName,
      List positionalArguments, Map<Symbol,dynamic> namedArguments) {

    var cache = _classInvocationCache;
    var cacheEntry = JsCache.fetch(cache, reflectiveName);
    var result;
    if (cacheEntry == null) {
      disableTreeShaking();
      String mangledName = reflectiveNames[reflectiveName];
      List<String> argumentNames = const [];

      // TODO(ahe): We don't need to create an invocation mirror here. The
      // logic from JSInvocationMirror.getCachedInvocation could easily be
      // inlined here.
      Invocation invocation = createUnmangledInvocationMirror(
          name, mangledName, type, positionalArguments, argumentNames);

      cacheEntry =
          JSInvocationMirror.getCachedInvocation(invocation, reflectee);
      JsCache.update(cache, reflectiveName, cacheEntry);
    }
    return cacheEntry;
  }

  bool _isReflectable(CachedInvocation cachedInvocation) {
    // TODO(floitsch): tear-off closure does not guarantee that the
    // function is reflectable.
    var method = cachedInvocation.jsFunction;
    return hasReflectableProperty(method) || reflectee is TearOffClosure;
  }

  /// Invoke the member specified through name and type on the reflectee.
  /// As a side-effect, this populates the class-specific invocation cache
  /// for the reflectee.
  InstanceMirror _invoke(Symbol name,
                         int type,
                         List positionalArguments,
                         Map<Symbol,dynamic> namedArguments) {
    String reflectiveName =
        _computeReflectiveName(name, type, positionalArguments, namedArguments);

    if (namedArguments.isNotEmpty) {
      // TODO(floitsch): first, make sure it's not a getter.
      return _invokeMethodWithNamedArguments(
          reflectiveName, positionalArguments, namedArguments);
    }
    var cacheEntry = _getCachedInvocation(
        name, type, reflectiveName, positionalArguments, namedArguments);

    if (cacheEntry.isNoSuchMethod || !_isReflectable(cacheEntry)) {
      // Could be that we want to invoke a getter, or get a method.
      if (type == JSInvocationMirror.METHOD && _instanceFieldExists(name)) {
        return getField(name).invoke(
            #call, positionalArguments, namedArguments);
      }

      if (type == JSInvocationMirror.SETTER) {
        // For setters we report the setter name "field=".
        name = s("${n(name)}=");
      }

      if (!cacheEntry.isNoSuchMethod) {
        // Not reflectable.
        throwInvalidReflectionError(reflectiveName);
      }

      String mangledName = reflectiveNames[reflectiveName];
      // TODO(ahe): Get the argument names.
      List<String> argumentNames = [];
      Invocation invocation = createUnmangledInvocationMirror(
          name, mangledName, type, positionalArguments, argumentNames);
      return reflect(cacheEntry.invokeOn(reflectee, invocation));
    } else {
      return reflect(cacheEntry.invokeOn(reflectee, positionalArguments));
    }
  }

  InstanceMirror setField(Symbol fieldName, Object arg) {
    _invoke(fieldName, JSInvocationMirror.SETTER, [arg], const {});
    return reflect(arg);
  }

  // JS helpers for getField optimizations.
  static bool isUndefined(x)
      => JS('bool', 'typeof # == "undefined"', x);
  static bool isMissingCache(x)
      => JS('bool', 'typeof # == "number"', x);
  static bool isMissingProbe(Symbol symbol)
      => JS('bool', 'typeof #.\$p == "undefined"', symbol);
  static bool isEvalAllowed()
      => !JS_GET_FLAG("USE_CONTENT_SECURITY_POLICY");


  /// The getter cache is lazily allocated after a couple
  /// of invocations of [InstanceMirror.getField]. The delay is
  /// used to avoid too aggressive caching and dynamic function
  /// generation for rarely used mirrors. The cache is specific to
  /// this [InstanceMirror] and maps reflective names to functions
  /// that will invoke the corresponding getter on the reflectee.
  /// The reflectee is passed to the function as the first argument
  /// to avoid the overhead of fetching it from this mirror repeatedly.
  /// The cache is lazily initialized to a JS object so we can
  /// benefit from "map transitions" in the underlying JavaScript
  /// engine to speed up cache probing.
  var _getterCache = 4;

  bool _instanceFieldExists(Symbol name) {
    int getterType = JSInvocationMirror.GETTER;
    String getterName =
        _computeReflectiveName(name, getterType, const [], const {});
    var getterCacheEntry = _getCachedInvocation(
        name, getterType, getterName, const [], const {});
    return !getterCacheEntry.isNoSuchMethod && !getterCacheEntry.isGetterStub;
  }

  InstanceMirror getField(Symbol fieldName) {
    FASTPATH: {
      var cache = _getterCache;
      if (isMissingCache(cache) || isMissingProbe(fieldName)) break FASTPATH;
      // If the [fieldName] has an associated probe function, we can use
      // it to read from the getter cache specific to this [InstanceMirror].
      var getter = JS('', '#.\$p(#)', fieldName, cache);
      if (isUndefined(getter)) break FASTPATH;
      // Call the getter passing the reflectee as the first argument.
      var value = JS('', '#(#)', getter, reflectee);
      // The getter has an associate cache of the last [InstanceMirror]
      // returned to avoid repeated invocations of [reflect]. To validate
      // the cache, we check that the value returned by the getter is the
      // same value as last time.
      if (JS('bool', '# === #.v', value, getter)) {
        return JS('InstanceMirror', '#.m', getter);
      } else {
        var result = reflect(value);
        JS('void', '#.v = #', getter, value);
        JS('void', '#.m = #', getter, result);
        return result;
      }
    }
    return _getFieldSlow(fieldName);
  }

  InstanceMirror _getFieldSlow(Symbol fieldName) {
    // First do the slow-case getter invocation. As a side-effect of this,
    // the invocation cache is filled in so we can query it afterwards.
    var result =
        _invoke(fieldName, JSInvocationMirror.GETTER, const [], const {});
    String name = n(fieldName);
    var cacheEntry = JsCache.fetch(_classInvocationCache, name);
    if (cacheEntry.isNoSuchMethod) {
      return result;
    }

    // Make sure we have a getter cache in this [InstanceMirror].
    var cache = _getterCache;
    if (isMissingCache(cache)) {
      if ((_getterCache = --cache) != 0) return result;
      cache = _getterCache = JS('=Object', 'Object.create(null)');
    }

    // Make sure that symbol [fieldName] has a cache probing function ($p).
    bool useEval = isEvalAllowed();
    if (isMissingProbe(fieldName)) {
      var probe = _newProbeFn(name, useEval);
      JS('void', '#.\$p = #', fieldName, probe);
    }

    // Create a new getter function and install it in the cache.
    var mangledName = cacheEntry.mangledName;
    var getter = (cacheEntry.isIntercepted)
        ? _newInterceptedGetterFn(mangledName, useEval)
        : _newGetterFn(mangledName, useEval);
    JS('void', '#[#] = #', cache, name, getter);

    // Initialize the last value (v) and last mirror (m) on the
    // newly generated getter to be a sentinel value that is hard
    // to get hold of through user code.
    JS('void', '#.v = #.m = #', getter, getter, cache);

    // Return the result of the slow-path getter invocation.
    return result;
  }

  _newProbeFn(String id, bool useEval) {
    if (useEval) {
      String body = "return c.$id;";
      return JS('', 'new Function("c", #)', body);
    } else {
      return JS('', '(function(n){return(function(c){return c[n]})})(#)', id);
    }
  }

  _newGetterFn(String name, bool useEval) {
    if (!useEval) return _newGetterNoEvalFn(name);
    // We use a comment that associates the generated function with the
    // class of the reflectee. This makes it more likely that the underlying
    // JavaScript engine will only share the generated code for accessors on the
    // same class (through caching of eval'ed code). This makes the
    // generated call to the getter - e.g. o.get$foo() - much more likely
    // to be monomorphic and inlineable.
    String className = JS('String', '#.constructor.name', reflectee);
    String body = "/* $className */ return o.$name();";
    return JS('', 'new Function("o", #)', body);
  }

  _newGetterNoEvalFn(n) => JS('',
      '(function(n){return(function(o){return o[n]()})})(#)', n);

  _newInterceptedGetterFn(String name, bool useEval) {
    var object = reflectee;
    // It is possible that the interceptor for a given object is the object
    // itself, so it is important not to share the code that captures the
    // interceptor between multiple different instances of [InstanceMirror].
    var interceptor = getInterceptor(object);
    if (!useEval) return _newInterceptGetterNoEvalFn(name, interceptor);
    String className = JS('String', '#.constructor.name', interceptor);
    String functionName = '$className\$$name';
    String body =
        '  function $functionName(o){return i.$name(o)}'
        '  return $functionName;';
    return JS('', '(new Function("i", #))(#)', body, interceptor);
  }

  _newInterceptGetterNoEvalFn(n, i) => JS('',
      '(function(n,i){return(function(o){return i[n](o)})})(#,#)', n, i);

  delegate(Invocation invocation) {
    return JSInvocationMirror.invokeFromMirror(invocation, reflectee);
  }

  operator ==(other) {
    return other is JsInstanceMirror &&
           identical(reflectee, other.reflectee);
  }

  int get hashCode {
    // Avoid hash collisions with the reflectee. This constant is in Smi range
    // and happens to be the inner padding from RFC 2104.
    return identityHashCode(reflectee) ^ 0x36363636;
  }

  String toString() => 'InstanceMirror on ${Error.safeToString(reflectee)}';

  // TODO(ahe): Remove this method from the API.
  MirrorSystem get mirrors => currentJsMirrorSystem;
}

/**
 * ClassMirror for generic classes where the type parameters are bound.
 *
 * [typeArguments] will return a list of the type arguments, in constrast
 * to JsCLassMirror that returns an empty list since it represents original
 * declarations and classes that are not generic.
 */
class JsTypeBoundClassMirror extends JsDeclarationMirror
    implements ClassMirror {
  final JsClassMirror _class;

  /**
   * When instantiated this field will hold a string representing the list of
   * type arguments for the class, i.e. what is inside the outermost angle
   * brackets. Then, when get typeArguments is called the first time, the string
   * is parsed into the actual list of TypeMirrors, and stored in
   * [_cachedTypeArguments]. Due to type substitution of, for instance,
   * superclasses the mangled name of the class and hence this string is needed
   * after [_cachedTypeArguments] has been computed.
   *
   * If an integer is encountered as a type argument, it represents the type
   * variable at the corresponding entry in [emitter.globalMetadata].
   */
  String _typeArguments;

  UnmodifiableListView<TypeMirror> _cachedTypeArguments;
  UnmodifiableMapView<Symbol, DeclarationMirror> _cachedDeclarations;
  UnmodifiableMapView<Symbol, DeclarationMirror> _cachedMembers;
  UnmodifiableMapView<Symbol, MethodMirror> _cachedConstructors;
  Map<Symbol, VariableMirror> _cachedVariables;
  Map<Symbol, MethodMirror> _cachedGetters;
  Map<Symbol, MethodMirror> _cachedSetters;
  Map<Symbol, MethodMirror> _cachedMethodsMap;
  List<JsMethodMirror> _cachedMethods;
  ClassMirror _superclass;
  List<ClassMirror> _cachedSuperinterfaces;
  Map<Symbol, MethodMirror> _cachedInstanceMembers;
  Map<Symbol, MethodMirror> _cachedStaticMembers;

  JsTypeBoundClassMirror(JsClassMirror originalDeclaration, this._typeArguments)
      : _class = originalDeclaration,
        super(originalDeclaration.simpleName);

  String get _prettyName => 'ClassMirror';

  String toString() {
    String result = '$_prettyName on ${n(simpleName)}';
    if (typeArguments != null) {
      result = "$result<${typeArguments.join(', ')}>";
    }
    return result;
  }

  String get _mangledName {
    for (TypeMirror typeArgument in typeArguments) {
      if (typeArgument != JsMirrorSystem._dynamicType) {
        return '${_class._mangledName}<$_typeArguments>';
      }
    }
    // When all type arguments are dynamic, the canonical representation is to
    // drop them.
    return _class._mangledName;
  }

  List<TypeVariableMirror> get typeVariables => _class.typeVariables;

  List<TypeMirror> get typeArguments {
    if (_cachedTypeArguments != null) return _cachedTypeArguments;
    List result = new List();

    addTypeArgument(String typeArgument) {
      int parsedIndex = int.parse(typeArgument, onError: (_) => -1);
      if (parsedIndex == -1) {
        result.add(reflectClassByMangledName(typeArgument.trim()));
      } else {
        TypeVariable typeVariable = getMetadata(parsedIndex);
        TypeMirror owner = reflectClass(typeVariable.owner);
        TypeVariableMirror typeMirror =
            new JsTypeVariableMirror(typeVariable, owner, parsedIndex);
        result.add(typeMirror);
      }
    }

    if (_typeArguments.indexOf('<') == -1) {
      _typeArguments.split(',').forEach((t) => addTypeArgument(t));
    } else {
      int level = 0;
      String currentTypeArgument = '';

      for (int i = 0; i < _typeArguments.length; i++) {
        var character = _typeArguments[i];
        if (character == ' ') {
          continue;
        } else if (character == '<') {
          currentTypeArgument += character;
          level++;
        } else if (character == '>') {
          currentTypeArgument += character;
          level--;
        } else if (character == ',') {
          if (level > 0) {
            currentTypeArgument += character;
          } else {
            addTypeArgument(currentTypeArgument);
            currentTypeArgument = '';
          }
        } else {
          currentTypeArgument += character;
        }
      }
      addTypeArgument(currentTypeArgument);
    }
    return _cachedTypeArguments = new UnmodifiableListView(result);
  }

  List<JsMethodMirror> get _methods {
    if (_cachedMethods != null) return _cachedMethods;
    return _cachedMethods =_class._getMethodsWithOwner(this);
  }

  Map<Symbol, MethodMirror> get __methods {
    if (_cachedMethodsMap != null) return _cachedMethodsMap;
    return _cachedMethodsMap = new UnmodifiableMapView<Symbol, MethodMirror>(
        filterMethods(_methods));
  }

  Map<Symbol, MethodMirror> get __constructors {
    if (_cachedConstructors != null) return _cachedConstructors;
    return _cachedConstructors =
        new UnmodifiableMapView<Symbol, MethodMirror>(
            filterConstructors(_methods));
  }

  Map<Symbol, MethodMirror> get __getters {
    if (_cachedGetters != null) return _cachedGetters;
    return _cachedGetters = new UnmodifiableMapView<Symbol, MethodMirror>(
        filterGetters(_methods, __variables));
  }

  Map<Symbol, MethodMirror> get __setters {
    if (_cachedSetters != null) return _cachedSetters;
    return _cachedSetters = new UnmodifiableMapView<Symbol, MethodMirror>(
        filterSetters(_methods, __variables));
  }

  Map<Symbol, VariableMirror> get __variables {
    if (_cachedVariables != null) return _cachedVariables;
    var result = new Map();
    for (JsVariableMirror mirror in  _class._getFieldsWithOwner(this)) {
      result[mirror.simpleName] = mirror;
    }
    return _cachedVariables =
        new UnmodifiableMapView<Symbol, VariableMirror>(result);
  }

  Map<Symbol, DeclarationMirror> get __members {
    if (_cachedMembers != null) return _cachedMembers;
    return _cachedMembers = new UnmodifiableMapView<Symbol, DeclarationMirror>(
        filterMembers(_methods, __variables));
  }

  Map<Symbol, DeclarationMirror> get declarations {
    if (_cachedDeclarations != null) return _cachedDeclarations;
    Map<Symbol, DeclarationMirror> result =
        new Map<Symbol, DeclarationMirror>();
    result.addAll(__members);
    result.addAll(__constructors);
    typeVariables.forEach((tv) => result[tv.simpleName] = tv);
    return _cachedDeclarations =
        new UnmodifiableMapView<Symbol, DeclarationMirror>(result);
  }

  Map<Symbol, MethodMirror> get staticMembers {
    if (_cachedStaticMembers == null) {
      var result = new Map<Symbol, MethodMirror>();
      declarations.values.forEach((decl) {
        if (decl is MethodMirror && decl.isStatic && !decl.isConstructor) {
          result[decl.simpleName] = decl;
        }
        if (decl is VariableMirror && decl.isStatic) {
          var getterName = decl.simpleName;
          result[getterName] = new JsSyntheticAccessor(
              this, getterName, true, true, false, decl);
          if (!decl.isFinal) {
            var setterName = setterSymbol(decl.simpleName);
            result[setterName] = new JsSyntheticAccessor(
                this, setterName, false, true, false, decl);
          }
        }
      });
      _cachedStaticMembers = result;
    }
    return _cachedStaticMembers;
  }

  Map<Symbol, MethodMirror> get instanceMembers {
    if (_cachedInstanceMembers == null) {
      var result = new Map<Symbol, MethodMirror>();
      if (superclass != null) {
        result.addAll(superclass.instanceMembers);
      }
      declarations.values.forEach((decl) {
        if (decl is MethodMirror && !decl.isStatic &&
            !decl.isConstructor && !decl.isAbstract) {
          result[decl.simpleName] = decl;
        }
        if (decl is VariableMirror && !decl.isStatic) {
          var getterName = decl.simpleName;
          result[getterName] = new JsSyntheticAccessor(
              this, getterName, true, false, false, decl);
          if (!decl.isFinal) {
            var setterName = setterSymbol(decl.simpleName);
            result[setterName] = new JsSyntheticAccessor(
                this, setterName, false, false, false, decl);
          }
        }
      });
      _cachedInstanceMembers = result;
    }
    return _cachedInstanceMembers;
  }

  InstanceMirror setField(Symbol fieldName, Object arg) {
    return _class.setField(fieldName, arg);
  }

  InstanceMirror getField(Symbol fieldName) => _class.getField(fieldName);

  InstanceMirror newInstance(Symbol constructorName,
                             List positionalArguments,
                             [Map<Symbol, dynamic> namedArguments]) {
    var instance = _class._getInvokedInstance(constructorName,
                                              positionalArguments,
                                              namedArguments);
    return reflect(setRuntimeTypeInfo(
        instance, typeArguments.map((t) => t._asRuntimeType()).toList()));
  }

  _asRuntimeType() {
    return [_class._jsConstructor].addAll(
        typeArguments.map((t) => t._asRuntimeType()));
  }

  JsLibraryMirror get owner => _class.owner;

  List<InstanceMirror> get metadata => _class.metadata;

  ClassMirror get superclass {
    if (_superclass != null) return _superclass;

    var typeInformationContainer = JS_EMBEDDED_GLOBAL('', TYPE_INFORMATION);
    List<int> typeInformation =
        JS('List|Null', '#[#]', typeInformationContainer, _class._mangledName);
    assert(typeInformation != null);
    var type = getType(typeInformation[0]);
    return _superclass = typeMirrorFromRuntimeTypeRepresentation(this, type);
  }

  InstanceMirror invoke(Symbol memberName,
                        List positionalArguments,
                        [Map<Symbol,dynamic> namedArguments]) {
    return _class.invoke(memberName, positionalArguments, namedArguments);
  }

  bool get isOriginalDeclaration => false;

  ClassMirror get originalDeclaration => _class;

  List<ClassMirror> get superinterfaces {
    if (_cachedSuperinterfaces != null) return _cachedSuperinterfaces;
    return _cachedSuperinterfaces = _class._getSuperinterfacesWithOwner(this);
  }

  bool get isPrivate => _class.isPrivate;

  bool get isTopLevel => _class.isTopLevel;

  bool get isAbstract => _class.isAbstract;

  bool get isEnum => _class.isEnum;

  bool isSubclassOf(ClassMirror other) => _class.isSubclassOf(other);

  SourceLocation get location => _class.location;

  MirrorSystem get mirrors => _class.mirrors;

  Symbol get qualifiedName => _class.qualifiedName;

  bool get hasReflectedType => true;

  Type get reflectedType => createRuntimeType(_mangledName);

  Symbol get simpleName => _class.simpleName;

  // TODO(ahe): Implement this.
  ClassMirror get mixin => throw new UnimplementedError();

  bool isSubtypeOf(TypeMirror other) => throw new UnimplementedError();

  bool isAssignableTo(TypeMirror other) => throw new UnimplementedError();
}

class JsSyntheticAccessor implements MethodMirror {
  final DeclarationMirror owner;
  final Symbol simpleName;
  final bool isGetter;
  final bool isStatic;
  final bool isTopLevel;
  final _target;  /// The field or type that introduces the synthetic accessor.

  JsSyntheticAccessor(this.owner,
                      this.simpleName,
                      this.isGetter,
                      this.isStatic,
                      this.isTopLevel,
                      this._target);

  bool get isSynthetic => true;
  bool get isRegularMethod => false;
  bool get isOperator => false;
  bool get isConstructor => false;
  bool get isConstConstructor => false;
  bool get isGenerativeConstructor => false;
  bool get isFactoryConstructor => false;
  bool get isRedirectingConstructor => false;
  bool get isAbstract => false;

  bool get isSetter => !isGetter;
  bool get isPrivate => n(simpleName).startsWith('_');

  Symbol get qualifiedName => computeQualifiedName(owner, simpleName);
  Symbol get constructorName => const Symbol('');

  TypeMirror get returnType => _target.type;
  List<ParameterMirror> get parameters {
    if (isGetter) return const [];
    return new UnmodifiableListView(
        [new JsSyntheticSetterParameter(this, this._target)]);
  }

  List<InstanceMirror> get metadata => const [];
  String get source => null;
  SourceLocation get location => throw new UnimplementedError();
}

class JsSyntheticSetterParameter implements ParameterMirror {
  final DeclarationMirror owner;
  final VariableMirror _target;

  JsSyntheticSetterParameter(this.owner, this._target);

  Symbol get simpleName => _target.simpleName;
  Symbol get qualifiedName => computeQualifiedName(owner, simpleName);
  TypeMirror get type => _target.type;

  bool get isOptional => false;
  bool get isNamed => false;
  bool get isStatic => false;
  bool get isTopLevel => false;
  bool get isConst => false;
  bool get isFinal => true;
  bool get isPrivate => false;
  bool get hasDefaultValue => false;
  InstanceMirror get defaultValue => null;
  List<InstanceMirror> get metadata => const [];
  SourceLocation get location => throw new UnimplementedError();
}

class JsClassMirror extends JsTypeMirror with JsObjectMirror
    implements ClassMirror {
  final String _mangledName;
  final _jsConstructor;
  final String _fieldsDescriptor;
  final List _fieldsMetadata;
  final _jsConstructorCache = JsCache.allocate();
  List _metadata;
  ClassMirror _superclass;
  List<JsMethodMirror> _cachedMethods;
  List<VariableMirror> _cachedFields;
  UnmodifiableMapView<Symbol, MethodMirror> _cachedConstructors;
  UnmodifiableMapView<Symbol, MethodMirror> _cachedMethodsMap;
  UnmodifiableMapView<Symbol, MethodMirror> _cachedGetters;
  UnmodifiableMapView<Symbol, MethodMirror> _cachedSetters;
  UnmodifiableMapView<Symbol, VariableMirror> _cachedVariables;
  UnmodifiableMapView<Symbol, Mirror> _cachedMembers;
  UnmodifiableMapView<Symbol, DeclarationMirror> _cachedDeclarations;
  UnmodifiableListView<InstanceMirror> _cachedMetadata;
  UnmodifiableListView<ClassMirror> _cachedSuperinterfaces;
  UnmodifiableListView<TypeVariableMirror> _cachedTypeVariables;
  Map<Symbol, MethodMirror> _cachedInstanceMembers;
  Map<Symbol, MethodMirror> _cachedStaticMembers;

  // Set as side-effect of accessing JsLibraryMirror.classes.
  JsLibraryMirror _owner;

  JsClassMirror(Symbol simpleName,
                this._mangledName,
                this._jsConstructor,
                this._fieldsDescriptor,
                this._fieldsMetadata)
      : super(simpleName);

  String get _prettyName => 'ClassMirror';

  Map<Symbol, MethodMirror> get __constructors {
    if (_cachedConstructors != null) return _cachedConstructors;
    return _cachedConstructors =
        new UnmodifiableMapView<Symbol, MethodMirror>(
            filterConstructors(_methods));
  }

  _asRuntimeType() {
    if (typeVariables.isEmpty)  return _jsConstructor;
    var type = [_jsConstructor];
    for (int i = 0; i < typeVariables.length; i ++) {
      type.add(JsMirrorSystem._dynamicType._asRuntimeType);
    }
    return type;
  }

  List<JsMethodMirror> _getMethodsWithOwner(DeclarationMirror methodOwner) {
    var prototype = JS('', '#.prototype', _jsConstructor);
    // The prototype might not have been processed yet, so do that now.
    JS('', '#[#]()', prototype,
                     JS_GET_NAME(JsGetName.DEFERRED_ACTION_PROPERTY));
    List<String> keys = extractKeys(prototype);
    var result = <JsMethodMirror>[];
    for (String key in keys) {
      if (isReflectiveDataInPrototype(key)) continue;
      String simpleName = mangledNames[key];
      // [simpleName] can be null if [key] represents an implementation
      // detail, for example, a bailout method, or runtime type support.
      // It might also be null if the user has limited what is reified for
      // reflection with metadata.
      if (simpleName == null) continue;
      var function = JS('', '#[#]', prototype, key);
      if (!isOrdinaryReflectableMethod(function)) continue;
      if (isAliasedSuperMethod(function, key)) continue;
      var mirror =
          new JsMethodMirror.fromUnmangledName(
              simpleName, function, false, false);
      result.add(mirror);
      mirror._owner = methodOwner;
    }

    var statics = JS_EMBEDDED_GLOBAL('', STATICS);
    keys = extractKeys(JS('', '#[#]', statics, _mangledName));
    for (String mangledName in keys) {
      if (isReflectiveDataInPrototype(mangledName)) continue;
      String unmangledName = mangledName;
      var jsFunction = JS('', '#[#]', owner._globalObject, mangledName);

      bool isConstructor = false;
      if (hasReflectableProperty(jsFunction)) {
        String reflectionName =
            JS('String|Null', r'#.$reflectionName', jsFunction);
        if (reflectionName == null) continue;
        isConstructor = reflectionName.startsWith('new ');
        if (isConstructor) {
          reflectionName = reflectionName.substring(4).replaceAll(r'$', '.');
        }
        unmangledName = reflectionName;
      } else {
        continue;
      }
      bool isStatic = !isConstructor; // Constructors are not static.
      JsMethodMirror mirror =
          new JsMethodMirror.fromUnmangledName(
              unmangledName, jsFunction, isStatic, isConstructor);
      result.add(mirror);
      mirror._owner = methodOwner;
    }

    return result;
  }

  List<JsMethodMirror> get _methods {
    if (_cachedMethods != null) return _cachedMethods;
    return _cachedMethods = _getMethodsWithOwner(this);
  }

  List<VariableMirror> _getFieldsWithOwner(DeclarationMirror fieldOwner) {
    var result = <VariableMirror>[];

    var instanceFieldSpecfication = _fieldsDescriptor.split(';')[1];
    if (_fieldsMetadata != null) {
      instanceFieldSpecfication =
          [instanceFieldSpecfication]..addAll(_fieldsMetadata);
    }
    parseCompactFieldSpecification(
        fieldOwner, instanceFieldSpecfication, false, result);

    var statics = JS_EMBEDDED_GLOBAL('', STATICS);
    var staticDescriptor = JS('', '#[#]', statics, _mangledName);
    if (staticDescriptor != null) {
      parseCompactFieldSpecification(
          fieldOwner,
          JS('', '#[#]',
              staticDescriptor,
              JS_GET_NAME(JsGetName.CLASS_DESCRIPTOR_PROPERTY)),
          true, result);
    }
    return result;
  }

  List<VariableMirror> get _fields {
    if (_cachedFields != null) return _cachedFields;
    return _cachedFields = _getFieldsWithOwner(this);
  }

  Map<Symbol, MethodMirror> get __methods {
    if (_cachedMethodsMap != null) return _cachedMethodsMap;
    return _cachedMethodsMap =
        new UnmodifiableMapView<Symbol, MethodMirror>(filterMethods(_methods));
  }

  Map<Symbol, MethodMirror> get __getters {
    if (_cachedGetters != null) return _cachedGetters;
    return _cachedGetters = new UnmodifiableMapView<Symbol, MethodMirror>(
        filterGetters(_methods, __variables));
  }

  Map<Symbol, MethodMirror> get __setters {
    if (_cachedSetters != null) return _cachedSetters;
    return _cachedSetters = new UnmodifiableMapView<Symbol, MethodMirror>(
        filterSetters(_methods, __variables));
  }

  Map<Symbol, VariableMirror> get __variables {
    if (_cachedVariables != null) return _cachedVariables;
    var result = new Map();
    for (JsVariableMirror mirror in _fields) {
      result[mirror.simpleName] = mirror;
    }
    return _cachedVariables =
        new UnmodifiableMapView<Symbol, VariableMirror>(result);
  }

  Map<Symbol, Mirror> get __members {
    if (_cachedMembers != null) return _cachedMembers;
    return _cachedMembers = new UnmodifiableMapView<Symbol, Mirror>(
        filterMembers(_methods, __variables));
  }

  Map<Symbol, DeclarationMirror> get declarations {
    if (_cachedDeclarations != null) return _cachedDeclarations;
    var result = new Map<Symbol, DeclarationMirror>();
    addToResult(Symbol key, Mirror value) {
      result[key] = value;
    }
    __members.forEach(addToResult);
    __constructors.forEach(addToResult);
    typeVariables.forEach((tv) => result[tv.simpleName] = tv);
    return _cachedDeclarations =
        new UnmodifiableMapView<Symbol, DeclarationMirror>(result);
  }

  Map<Symbol, MethodMirror> get staticMembers {
    if (_cachedStaticMembers == null) {
      var result = new Map<Symbol, MethodMirror>();
      declarations.values.forEach((decl) {
        if (decl is MethodMirror && decl.isStatic && !decl.isConstructor) {
          result[decl.simpleName] = decl;
        }
        if (decl is VariableMirror && decl.isStatic) {
          var getterName = decl.simpleName;
          result[getterName] = new JsSyntheticAccessor(
              this, getterName, true, true, false, decl);
          if (!decl.isFinal) {
            var setterName = setterSymbol(decl.simpleName);
            result[setterName] = new JsSyntheticAccessor(
                this, setterName, false, true, false, decl);
          }
        }
      });
      _cachedStaticMembers = result;
    }
    return _cachedStaticMembers;
  }

  Map<Symbol, MethodMirror> get instanceMembers {
    if (_cachedInstanceMembers == null) {
      var result = new Map<Symbol, MethodMirror>();
      if (superclass != null) {
        result.addAll(superclass.instanceMembers);
      }
      declarations.values.forEach((decl) {
        if (decl is MethodMirror && !decl.isStatic &&
            !decl.isConstructor && !decl.isAbstract) {
          result[decl.simpleName] = decl;
        }
        if (decl is VariableMirror && !decl.isStatic) {
          var getterName = decl.simpleName;
          result[getterName] = new JsSyntheticAccessor(
              this, getterName, true, false, false, decl);
          if (!decl.isFinal) {
            var setterName = setterSymbol(decl.simpleName);
            result[setterName] = new JsSyntheticAccessor(
                this, setterName, false, false, false, decl);
          }
        }
      });
      _cachedInstanceMembers = result;
    }
    return _cachedInstanceMembers;
  }

  InstanceMirror setField(Symbol fieldName, Object arg) {
    JsVariableMirror mirror = __variables[fieldName];
    if (mirror != null && mirror.isStatic && !mirror.isFinal) {
      // '$' (JS_GET_STATIC_STATE()) stores state which is stored directly, so
      // we shouldn't use [JsLibraryMirror._globalObject] here.
      String jsName = mirror._jsName;
      if (!JS('bool', '# in #', jsName, JS_GET_STATIC_STATE())) {
        throw new RuntimeError('Cannot find "$jsName" in current isolate.');
      }
      JS('void', '#[#] = #', JS_GET_STATIC_STATE(), jsName, arg);
      return reflect(arg);
    }
    Symbol setterName = setterSymbol(fieldName);
    if (mirror == null) {
      JsMethodMirror setter = __setters[setterName];
      if (setter != null) {
        setter._invoke([arg], const {});
        return reflect(arg);
      }
    }
    throw new NoSuchStaticMethodError.method(null, setterName, [arg], null);
  }

  bool _staticFieldExists(Symbol fieldName) {
    JsVariableMirror mirror = __variables[fieldName];
    if (mirror != null) return mirror.isStatic;
    JsMethodMirror getter = __getters[fieldName];
    return getter != null && getter.isStatic;
  }

  InstanceMirror getField(Symbol fieldName) {
    JsVariableMirror mirror = __variables[fieldName];
    if (mirror != null && mirror.isStatic) {
      String jsName = mirror._jsName;
      // '$' (JS_GET_STATIC_STATE()) stores state which is read directly, so
      // we shouldn't use [JsLibraryMirror._globalObject] here.
      if (!JS('bool', '# in #', jsName, JS_GET_STATIC_STATE())) {
        throw new RuntimeError('Cannot find "$jsName" in current isolate.');
      }
      var lazies = JS_EMBEDDED_GLOBAL('', LAZIES);
      if (JS('bool', '# in #', jsName, lazies)) {
        String getterName = JS('String', '#[#]', lazies, jsName);
        return reflect(JS('', '#[#]()', JS_GET_STATIC_STATE(), getterName));
      } else {
        return reflect(JS('', '#[#]', JS_GET_STATIC_STATE(), jsName));
      }
    }
    JsMethodMirror getter = __getters[fieldName];
    if (getter != null && getter.isStatic) {
      return reflect(getter._invoke(const [], const {}));
    }
    // If the fieldName designates a static function we have to return
    // its closure.
    JsMethodMirror method = __methods[fieldName];
    if (method != null && method.isStatic) {
      // We invoke the same getter that Dart code would execute. During
      // initialization we have stored that getter on the function (so that
      // we can find it more easily here).
      var getter = JS("", "#['\$getter']", method._jsFunction);
      if (getter == null) throw new UnimplementedError();
      return reflect(JS("", "#()", getter));
    }
    throw new NoSuchStaticMethodError.method(null, fieldName, null, null);
  }

  _getInvokedInstance(Symbol constructorName,
                      List positionalArguments,
                      [Map<Symbol, dynamic> namedArguments]) {
     if (namedArguments != null && !namedArguments.isEmpty) {
       throw new UnsupportedError('Named arguments are not implemented.');
     }
     JsMethodMirror mirror =
         JsCache.fetch(_jsConstructorCache, n(constructorName));
     if (mirror == null) {
       mirror = __constructors.values.firstWhere(
           (m) => m.constructorName == constructorName,
           orElse: () {
             throw new NoSuchStaticMethodError.method(
                 null, constructorName, positionalArguments, namedArguments);
           });
       JsCache.update(_jsConstructorCache, n(constructorName), mirror);
     }
     return mirror._invoke(positionalArguments, namedArguments);
   }

  InstanceMirror newInstance(Symbol constructorName,
                             List positionalArguments,
                             [Map<Symbol, dynamic> namedArguments]) {
    return reflect(_getInvokedInstance(constructorName,
                                       positionalArguments,
                                       namedArguments));
  }

  JsLibraryMirror get owner {
    if (_owner == null) {
      for (var list in JsMirrorSystem.librariesByName.values) {
        for (JsLibraryMirror library in list) {
          // This will set _owner field on all classes as a side
          // effect.  This gives us a fast path to reflect on a
          // class without parsing reflection data.
          library.__classes;
        }
      }
      if (_owner == null) {
        throw new StateError('Class "${n(simpleName)}" has no owner');
      }
    }
    return _owner;
  }

  List<InstanceMirror> get metadata {
    if (_cachedMetadata != null) return _cachedMetadata;
    if (_metadata == null) {
      _metadata = extractMetadata(JS('', '#.prototype', _jsConstructor));
    }
    return _cachedMetadata =
        new UnmodifiableListView<InstanceMirror>(_metadata.map(reflect));
  }

  ClassMirror get superclass {
    if (_superclass == null) {
      var typeInformationContainer = JS_EMBEDDED_GLOBAL('', TYPE_INFORMATION);
      List<int> typeInformation =
          JS('List|Null', '#[#]', typeInformationContainer, _mangledName);
      if (typeInformation != null) {
        var type = getType(typeInformation[0]);
        _superclass = typeMirrorFromRuntimeTypeRepresentation(this, type);
      } else {
        var superclassName = _fieldsDescriptor.split(';')[0].split(':')[0];
        // TODO(zarah): Remove special handing of mixins.
        var mixins = superclassName.split('+');
        if (mixins.length > 1) {
          if (mixins.length != 2) {
            throw new RuntimeError('Strange mixin: $_fieldsDescriptor');
          }
          _superclass = reflectClassByMangledName(mixins[0]);
        } else {
          // Use _superclass == this to represent class with no superclass
          // (Object).
          _superclass = (superclassName == '')
              ? this : reflectClassByMangledName(superclassName);
          }
        }
      }
    return _superclass == this ? null : _superclass;
  }

  InstanceMirror invoke(Symbol memberName,
                        List positionalArguments,
                        [Map<Symbol,dynamic> namedArguments]) {
    // Mirror API gotcha: Calling [invoke] on a ClassMirror means invoke a
    // static method.

    if (namedArguments != null && !namedArguments.isEmpty) {
      throw new UnsupportedError('Named arguments are not implemented.');
    }
    JsMethodMirror mirror = __methods[memberName];

    if (mirror == null && _staticFieldExists(memberName)) {
      return getField(memberName)
          .invoke(#call, positionalArguments, namedArguments);
    }
    if (mirror == null || !mirror.isStatic) {
      throw new NoSuchStaticMethodError.method(
          null, memberName, positionalArguments, namedArguments);
    }
    if (!mirror.canInvokeReflectively()) {
      throwInvalidReflectionError(n(memberName));
    }
    return reflect(mirror._invoke(positionalArguments, namedArguments));
  }

  bool get isOriginalDeclaration => true;

  ClassMirror get originalDeclaration => this;

  List<ClassMirror> _getSuperinterfacesWithOwner(DeclarationMirror owner) {
    var typeInformationContainer = JS_EMBEDDED_GLOBAL('', TYPE_INFORMATION);
    List<int> typeInformation =
        JS('List|Null', '#[#]', typeInformationContainer, _mangledName);
    List<ClassMirror> result = const <ClassMirror>[];
    if (typeInformation != null) {
      ClassMirror lookupType(int i) {
        var type = getType(i);
        return typeMirrorFromRuntimeTypeRepresentation(owner, type);
      }

      //We skip the first since it is the supertype.
      result = typeInformation.skip(1).map(lookupType).toList();
    }

    return new UnmodifiableListView<ClassMirror>(result);
  }

  List<ClassMirror> get superinterfaces {
    if (_cachedSuperinterfaces != null) return _cachedSuperinterfaces;
    return _cachedSuperinterfaces = _getSuperinterfacesWithOwner(this);
  }

  List<TypeVariableMirror> get typeVariables {
   if (_cachedTypeVariables != null) return _cachedTypeVariables;
   List result = new List();
   List typeVariables =
        JS('JSExtendableArray|Null', '#.prototype["<>"]', _jsConstructor);
    if (typeVariables == null) return result;
    for (int i = 0; i < typeVariables.length; i++) {
      TypeVariable typeVariable = getMetadata(typeVariables[i]);
      result.add(new JsTypeVariableMirror(typeVariable, this,
                                          typeVariables[i]));
    }
    return _cachedTypeVariables = new UnmodifiableListView(result);
  }

  List<TypeMirror> get typeArguments => const <TypeMirror>[];

  bool get hasReflectedType => typeVariables.length == 0;

  Type get reflectedType {
    if (!hasReflectedType) {
      throw new UnsupportedError(
          "Declarations of generics have no reflected type");
    }
    return createRuntimeType(_mangledName);
  }

  // TODO(ahe): Implement this.
  ClassMirror get mixin => throw new UnimplementedError();

  bool get isAbstract => throw new UnimplementedError();

  bool get isEnum => throw new UnimplementedError();

  bool isSubclassOf(ClassMirror other) {
    if (other is! ClassMirror) {
      throw new ArgumentError(other);
    }
    if (other is JsFunctionTypeMirror) {
      return false;
    } if (other is JsClassMirror &&
          JS('bool', '# == #', other._jsConstructor, _jsConstructor)) {
      return true;
    } else if (superclass == null) {
      return false;
    } else {
      return superclass.isSubclassOf(other);
    }
  }
}

class JsVariableMirror extends JsDeclarationMirror implements VariableMirror {

  // TODO(ahe): The values in these fields are virtually untested.
  final String _jsName;
  final bool isFinal;
  final bool isStatic;
  final _metadataFunction;
  final DeclarationMirror _owner;
  final int _type;
  List _metadata;

  JsVariableMirror(Symbol simpleName,
                   this._jsName,
                   this._type,
                   this.isFinal,
                   this.isStatic,
                   this._metadataFunction,
                   this._owner)
      : super(simpleName);

  factory JsVariableMirror.from(String descriptor,
                                metadataFunction,
                                JsDeclarationMirror owner,
                                bool isStatic) {
    List<String> fieldInformation = descriptor.split('-');
    if (fieldInformation.length == 1) {
      // The field is not available for reflection.
      // TODO(ahe): Should return an unreflectable field.
      return null;
    }

    String field = fieldInformation[0];
    int length = field.length;
    var code = fieldCode(field.codeUnitAt(length - 1));
    bool isFinal = false;
    if (code == 0) return null; // Inherited field.
    bool hasGetter = (code & 3) != 0;
    bool hasSetter = (code >> 2) != 0;
    isFinal = !hasSetter;
    length--;
    String jsName;
    String accessorName = jsName = field.substring(0, length);
    int divider = field.indexOf(':');
    if (divider > 0) {
      accessorName = accessorName.substring(0, divider);
      jsName = field.substring(divider + 1);
    }
    var unmangledName;
    if (isStatic) {
      unmangledName = mangledGlobalNames[accessorName];
    } else {
      String getterPrefix = JS_GET_NAME(JsGetName.GETTER_PREFIX);
      unmangledName = mangledNames['$getterPrefix$accessorName'];
    }
    if (unmangledName == null) unmangledName = accessorName;
    if (!hasSetter) {
      // TODO(ahe): This is a hack to handle checked setters in checked mode.
      var setterName = s('$unmangledName=');
      for (JsMethodMirror method in owner._methods) {
        if (method.simpleName == setterName) {
          isFinal = false;
          break;
        }
      }
    }
    int type = int.parse(fieldInformation[1], onError: (_) => null);
    return new JsVariableMirror(s(unmangledName),
                                jsName,
                                type,
                                isFinal,
                                isStatic,
                                metadataFunction,
                                owner);
  }

  String get _prettyName => 'VariableMirror';

  TypeMirror get type {
    return typeMirrorFromRuntimeTypeRepresentation(owner, getType(_type));
  }

  DeclarationMirror get owner => _owner;

  List<InstanceMirror> get metadata {
    preserveMetadata();
    if (_metadata == null) {
      _metadata = (_metadataFunction == null)
          ? const [] : JS('', '#()', _metadataFunction);
    }
    return _metadata.map(reflect).toList();
  }

  static int fieldCode(int code) {
    if (code >= 60 && code <= 64) return code - 59;
    if (code >= 123 && code <= 126) return code - 117;
    if (code >= 37 && code <= 43) return code - 27;
    return 0;
  }

  _getField(JsMirror receiver) => receiver._loadField(_jsName);

  void _setField(JsMirror receiver, Object arg) {
    if (isFinal) {
      // TODO(floitsch): when the field is non-static we don't want to have
      // a mirror as receiver.
      if (isStatic) {
        throw new NoSuchStaticMethodError.method(
            null, setterSymbol(simpleName), [arg], null);
      }
      throw new NoSuchMethodError(this, setterSymbol(simpleName), [arg], null);
    }
    receiver._storeField(_jsName, arg);
  }

  // TODO(ahe): Implement this method.
  bool get isConst => throw new UnimplementedError();
}

class JsClosureMirror extends JsInstanceMirror implements ClosureMirror {
  JsClosureMirror(reflectee)
      : super(reflectee);

  MethodMirror get function {
    String cacheName = Primitives.mirrorFunctionCacheName;
    JsMethodMirror cachedFunction;
    // TODO(ahe): Restore caching.
    //= JS('JsMethodMirror|Null', r'#.constructor[#]', reflectee, cacheName);
    if (cachedFunction != null) return cachedFunction;
    disableTreeShaking();
    // TODO(ahe): What about optional parameters (named or not).
    String callPrefix = "${JS_GET_NAME(JsGetName.CALL_PREFIX)}\$";
    var extractCallName = JS('', r'''
function(reflectee) {
  var properties = Object.keys(reflectee.constructor.prototype);
  for (var i = 0; i < properties.length; i++) {
    var property = properties[i];
    if (# == property.substring(0, #) &&
        property[#] >= '0' &&
        property[#] <= '9') return property;
  }
  return null;
}
''', callPrefix, callPrefix.length, callPrefix.length, callPrefix.length);
    String callName = JS('String|Null', '#(#)', extractCallName, reflectee);
    if (callName == null) {
      throw new RuntimeError('Cannot find callName on "$reflectee"');
    }
    // TODO(floitsch): What about optional parameters?
    int parameterCount = int.parse(callName.split(r'$')[1]);
    if (reflectee is BoundClosure) {
      var target = BoundClosure.targetOf(reflectee);
      var self = BoundClosure.selfOf(reflectee);
      var name = mangledNames[BoundClosure.nameOf(reflectee)];
      if (name == null) {
        throwInvalidReflectionError(name);
      }
      cachedFunction = new JsMethodMirror.fromUnmangledName(
          name, target, false, false);
    } else {
      bool isStatic = true; // TODO(ahe): Compute isStatic correctly.
      var jsFunction = JS('', '#[#]', reflectee, callName);
      var dummyOptionalParameterCount = 0;
      cachedFunction = new JsMethodMirror(
          s(callName), jsFunction, parameterCount, dummyOptionalParameterCount,
          false, false, isStatic, false, false);
    }
    JS('void', r'#.constructor[#] = #', reflectee, cacheName, cachedFunction);
    return cachedFunction;
  }

  InstanceMirror apply(List positionalArguments,
                       [Map<Symbol, dynamic> namedArguments]) {
    return reflect(
        Function.apply(reflectee, positionalArguments, namedArguments));
  }

  String toString() => "ClosureMirror on '${Error.safeToString(reflectee)}'";

  // TODO(ahe): Implement this method.
  String get source => throw new UnimplementedError();
}

class JsMethodMirror extends JsDeclarationMirror implements MethodMirror {
  final _jsFunction;
  final int _requiredParameterCount;
  final int _optionalParameterCount;
  final bool isGetter;
  final bool isSetter;
  final bool isStatic;
  final bool isConstructor;
  final bool isOperator;
  DeclarationMirror _owner;
  List _metadata;
  TypeMirror _returnType;
  UnmodifiableListView<ParameterMirror> _parameters;

  JsMethodMirror(Symbol simpleName,
                 this._jsFunction,
                 this._requiredParameterCount,
                 this._optionalParameterCount,
                 this.isGetter,
                 this.isSetter,
                 this.isStatic,
                 this.isConstructor,
                 this.isOperator)
      : super(simpleName);

  factory JsMethodMirror.fromUnmangledName(String name,
                                           jsFunction,
                                           bool isStatic,
                                           bool isConstructor) {
    List<String> info = name.split(':');
    name = info[0];
    bool isOperator = isOperatorName(name);
    bool isSetter = !isOperator && name.endsWith('=');
    int requiredParameterCount = 0;
    int optionalParameterCount = 0;
    bool isGetter = false;
    if (info.length == 1) {
      if (isSetter) {
        requiredParameterCount = 1;
      } else {
        isGetter = true;
        requiredParameterCount = 0;
      }
    } else {
      ReflectionInfo reflectionInfo = new ReflectionInfo(jsFunction);
      requiredParameterCount = reflectionInfo.requiredParameterCount;
      optionalParameterCount = reflectionInfo.optionalParameterCount;
      assert(int.parse(info[1]) == requiredParameterCount
          + optionalParameterCount);
    }
    return new JsMethodMirror(
        s(name), jsFunction, requiredParameterCount, optionalParameterCount,
        isGetter, isSetter, isStatic, isConstructor, isOperator);
  }

  String get _prettyName => 'MethodMirror';

  int get _parameterCount => _requiredParameterCount + _optionalParameterCount;

  List<ParameterMirror> get parameters {
    if (_parameters != null) return _parameters;
    metadata; // Compute _parameters as a side-effect of extracting metadata.
    return _parameters;
  }

  bool canInvokeReflectively() {
    return hasReflectableProperty(_jsFunction);
  }

  DeclarationMirror get owner => _owner;

  TypeMirror get returnType {
    metadata; // Compute _returnType as a side-effect of extracting metadata.
    return _returnType;
  }

  List<InstanceMirror> get metadata {
    if (_metadata == null) {
      var raw = extractMetadata(_jsFunction);
      var formals = new List(_parameterCount);
      ReflectionInfo info = new ReflectionInfo(_jsFunction);
      if (info != null) {
        assert(_parameterCount
               == info.requiredParameterCount + info.optionalParameterCount);
        var functionType = info.functionType;
        var type;
        if (functionType is int) {
          type = new JsFunctionTypeMirror(info.computeFunctionRti(null), this);
          assert(_parameterCount == type.parameters.length);
        } else if (isTopLevel) {
          type = new JsFunctionTypeMirror(info.computeFunctionRti(null), owner);
        } else {
          TypeMirror ownerType = owner;
          JsClassMirror ownerClass = ownerType.originalDeclaration;
          type = new JsFunctionTypeMirror(
              info.computeFunctionRti(ownerClass._jsConstructor),
              owner);
        }
        // Constructors aren't reified with their return type.
        if (isConstructor) {
          _returnType = owner;
        } else {
          _returnType = type.returnType;
        }
        int i = 0;
        bool isNamed = info.areOptionalParametersNamed;
        for (JsParameterMirror parameter in type.parameters) {
          var name = info.parameterName(i);
          List<int> annotations = info.parameterMetadataAnnotations(i);
          var p;
          if (i < info.requiredParameterCount) {
            p = new JsParameterMirror(name, this, parameter._type,
                metadataList: annotations);
          } else {
            var defaultValue = info.defaultValue(i);
            p = new JsParameterMirror(
                name, this, parameter._type, metadataList: annotations,
                isOptional: true, isNamed: isNamed, defaultValue: defaultValue);
          }
          formals[i++] = p;
        }
      }
      _parameters = new UnmodifiableListView<ParameterMirror>(formals);
      _metadata = new UnmodifiableListView(raw.map(reflect));
    }
    return _metadata;
  }

  Symbol get constructorName {
    // TODO(ahe): I believe it is more appropriate to throw an exception or
    // return null.
    if (!isConstructor) return const Symbol('');
    String name = n(simpleName);
    int index = name.indexOf('.');
    if (index == -1) return const Symbol('');
    return s(name.substring(index + 1));
  }

  _invoke(List positionalArguments, Map<Symbol, dynamic> namedArguments) {
    if (namedArguments != null && !namedArguments.isEmpty) {
      throw new UnsupportedError('Named arguments are not implemented.');
    }
    if (!isStatic && !isConstructor) {
      throw new RuntimeError('Cannot invoke instance method without receiver.');
    }
    int positionalLength = positionalArguments.length;
    if (positionalLength < _requiredParameterCount ||
        positionalLength >  _parameterCount ||
        _jsFunction == null) {
      // TODO(ahe): What receiver to use?
      throw new NoSuchMethodError(
          owner, simpleName, positionalArguments, namedArguments);
    }
    if (positionalLength < _parameterCount) {
      // Fill up with default values.
      // Make a copy so we don't modify the input.
      positionalArguments = positionalArguments.toList();
      for (int i = positionalLength; i < parameters.length; i++) {
        JsParameterMirror parameter = parameters[i];
        positionalArguments.add(parameter.defaultValue.reflectee);
      }
    }
    // Using JS_GET_STATIC_STATE() ('$') here is actually correct, although
    // _jsFunction may not be a property of '$', most static functions do not
    // care who their receiver is. But to lazy getters, it is important that
    // 'this' is '$'.
    return JS('', r'#.apply(#, #)', _jsFunction, JS_GET_STATIC_STATE(),
              new List.from(positionalArguments));
  }

  _getField(JsMirror receiver) {
    if (isGetter) {
      return _invoke([], null);
    } else {
      // TODO(ahe): Closurize method.
      throw new UnimplementedError('getField on $receiver');
    }
  }

  _setField(JsMirror receiver, Object arg) {
    if (isSetter) {
      return _invoke([arg], null);
    } else {
      throw new NoSuchMethodError(this, setterSymbol(simpleName), [], null);
    }
  }

  // Abstract methods are tree-shaken away.
  bool get isAbstract => false;

  // TODO(ahe, 14633): This might not be true for all cases.
  bool get isSynthetic => false;

  // TODO(ahe): Test this.
  bool get isRegularMethod => !isGetter && !isSetter && !isConstructor;

  // TODO(ahe): Implement this method.
  bool get isConstConstructor => throw new UnimplementedError();

  // TODO(ahe): Implement this method.
  bool get isGenerativeConstructor => throw new UnimplementedError();

  // TODO(ahe): Implement this method.
  bool get isRedirectingConstructor => throw new UnimplementedError();

  // TODO(ahe): Implement this method.
  bool get isFactoryConstructor => throw new UnimplementedError();

  // TODO(ahe): Implement this method.
  String get source => throw new UnimplementedError();
}

class JsParameterMirror extends JsDeclarationMirror implements ParameterMirror {
  final DeclarationMirror owner;
  // A JS object representing the type.
  final _type;

  final bool isOptional;

  final bool isNamed;

  final int _defaultValue;

  final List<int> metadataList;

  JsParameterMirror(String unmangledName,
                    this.owner,
                    this._type,
                     {this.metadataList: const <int>[],
                     this.isOptional: false,
                     this.isNamed: false,
                     defaultValue})
      : _defaultValue = defaultValue,
        super(s(unmangledName));

  String get _prettyName => 'ParameterMirror';

  TypeMirror get type {
    return typeMirrorFromRuntimeTypeRepresentation(owner, _type);
  }

  // Only true for static fields, never for a parameter.
  bool get isStatic => false;

  // TODO(ahe): Implement this.
  bool get isFinal => false;

  // TODO(ahe): Implement this.
  bool get isConst => false;

  bool get hasDefaultValue => _defaultValue != null;

  get defaultValue {
    return hasDefaultValue ? reflect(getMetadata(_defaultValue)) : null;
  }

  List<InstanceMirror> get metadata {
    preserveMetadata();
    return metadataList.map((int i) => reflect(getMetadata(i))).toList();
  }
}

class JsTypedefMirror extends JsDeclarationMirror implements TypedefMirror {
  final String _mangledName;
  JsFunctionTypeMirror referent;

  JsTypedefMirror(Symbol simpleName,  this._mangledName, _typeData)
      : super(simpleName) {
    referent = new JsFunctionTypeMirror(_typeData, this);
  }

  JsFunctionTypeMirror get value => referent;

  String get _prettyName => 'TypedefMirror';

  bool get hasReflectedType => throw new UnimplementedError();

  Type get reflectedType => createRuntimeType(_mangledName);

  // TODO(floitsch): Implement this method.
  List<TypeVariableMirror> get typeVariables => throw new UnimplementedError();

  // TODO(floitsch): Implement this method.
  List<TypeMirror> get typeArguments => throw new UnimplementedError();

  bool get isOriginalDeclaration => true;

  TypeMirror get originalDeclaration => this;

  // TODO(floitsch): Implement this method.
  DeclarationMirror get owner => throw new UnimplementedError();

  // TODO(ahe): Implement this method.
  List<InstanceMirror> get metadata => throw new UnimplementedError();

  bool isSubtypeOf(TypeMirror other) => throw new UnimplementedError();
  bool isAssignableTo(TypeMirror other) => throw new UnimplementedError();
}

// TODO(ahe): Remove this class when API is updated.
class BrokenClassMirror {
  bool get hasReflectedType => throw new UnimplementedError();
  Type get reflectedType => throw new UnimplementedError();
  ClassMirror get superclass => throw new UnimplementedError();
  List<ClassMirror> get superinterfaces => throw new UnimplementedError();
  Map<Symbol, DeclarationMirror> get declarations
      => throw new UnimplementedError();
  Map<Symbol, MethodMirror> get instanceMembers
      => throw new UnimplementedError();
  Map<Symbol, MethodMirror> get staticMembers => throw new UnimplementedError();
  ClassMirror get mixin => throw new UnimplementedError();
  InstanceMirror newInstance(
      Symbol constructorName,
      List positionalArguments,
      [Map<Symbol, dynamic> namedArguments]) => throw new UnimplementedError();
  InstanceMirror invoke(Symbol memberName,
                        List positionalArguments,
                        [Map<Symbol, dynamic> namedArguments])
      => throw new UnimplementedError();
  InstanceMirror getField(Symbol fieldName) => throw new UnimplementedError();
  InstanceMirror setField(Symbol fieldName, Object value)
      => throw new UnimplementedError();
  List<TypeVariableMirror> get typeVariables => throw new UnimplementedError();
  List<TypeMirror> get typeArguments => throw new UnimplementedError();
  TypeMirror get originalDeclaration => throw new UnimplementedError();
  Symbol get simpleName => throw new UnimplementedError();
  Symbol get qualifiedName => throw new UnimplementedError();
  bool get isPrivate => throw new UnimplementedError();
  bool get isTopLevel => throw new UnimplementedError();
  SourceLocation get location => throw new UnimplementedError();
  List<InstanceMirror> get metadata => throw new UnimplementedError();
}

class JsFunctionTypeMirror extends BrokenClassMirror
    implements FunctionTypeMirror {
  final _typeData;
  String _cachedToString;
  TypeMirror _cachedReturnType;
  UnmodifiableListView<ParameterMirror> _cachedParameters;
  DeclarationMirror owner;

  JsFunctionTypeMirror(this._typeData, this.owner);

  bool get _hasReturnType {
    return JS('bool', '# in #',
        JS_GET_NAME(JsGetName.FUNCTION_TYPE_RETURN_TYPE_TAG), _typeData);
  }

  get _returnType {
    return JS('', '#[#]', _typeData,
        JS_GET_NAME(JsGetName.FUNCTION_TYPE_RETURN_TYPE_TAG));
  }

  bool get _isVoid {
    return JS('bool', '!!#[#]', _typeData,
        JS_GET_NAME(JsGetName.FUNCTION_TYPE_VOID_RETURN_TAG));
  }

  bool get _hasArguments {
    return JS('bool', '# in #',
              JS_GET_NAME(JsGetName.FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG),
               _typeData);
  }
  List get _arguments {
    return JS('JSExtendableArray', '#[#]',
              _typeData,
              JS_GET_NAME(JsGetName.FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG));
  }

  bool get _hasOptionalArguments {
    return JS('bool', '# in #',
              JS_GET_NAME(JsGetName.FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG),
              _typeData);
  }
  List get _optionalArguments {
    return JS('JSExtendableArray', '#[#]',
              _typeData,
              JS_GET_NAME(JsGetName.FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG));
  }

  bool get _hasNamedArguments {
    return JS('bool', '# in #',
              JS_GET_NAME(JsGetName.FUNCTION_TYPE_NAMED_PARAMETERS_TAG),
              _typeData);
  }
  get _namedArguments {
    return JS('=Object', '#[#]',
              _typeData,
              JS_GET_NAME(JsGetName.FUNCTION_TYPE_NAMED_PARAMETERS_TAG));
  }

  bool get isOriginalDeclaration => true;

  bool get isAbstract => false;

  bool get isEnum => false;

  TypeMirror get returnType {
    if (_cachedReturnType != null) return _cachedReturnType;
    if (_isVoid) return _cachedReturnType = JsMirrorSystem._voidType;
    if (!_hasReturnType) return _cachedReturnType = JsMirrorSystem._dynamicType;
    return _cachedReturnType =
        typeMirrorFromRuntimeTypeRepresentation(owner, _returnType);
  }

  List<ParameterMirror> get parameters {
    if (_cachedParameters != null) return _cachedParameters;
    List result = [];
    int parameterCount = 0;
    if (_hasArguments) {
      for (var type in _arguments) {
        result.add(
            new JsParameterMirror('argument${parameterCount++}', this, type));
      }
    }
    if (_hasOptionalArguments) {
      for (var type in _optionalArguments) {
        result.add(
            new JsParameterMirror('argument${parameterCount++}', this, type));
      }
    }
    if (_hasNamedArguments) {
      for (var name in extractKeys(_namedArguments)) {
        var type = JS('', '#[#]', _namedArguments, name);
        result.add(new JsParameterMirror(name, this, type));
      }
    }
    return _cachedParameters = new UnmodifiableListView<ParameterMirror>(
        result);
  }

  String _unmangleIfPreserved(String mangled) {
    String result = unmangleGlobalNameIfPreservedAnyways(mangled);
    if (result != null) return result;
    return mangled;
  }

  String toString() {
    if (_cachedToString != null) return _cachedToString;
    var s = "FunctionTypeMirror on '(";
    var sep = '';
    if (_hasArguments) {
      for (var argument in _arguments) {
        s += sep;
        s += _unmangleIfPreserved(runtimeTypeToString(argument));
        sep = ', ';
      }
    }
    if (_hasOptionalArguments) {
      s += '$sep[';
      sep = '';
      for (var argument in _optionalArguments) {
        s += sep;
        s += _unmangleIfPreserved(runtimeTypeToString(argument));
        sep = ', ';
      }
      s += ']';
    }
    if (_hasNamedArguments) {
      s += '$sep{';
      sep = '';
      for (var name in extractKeys(_namedArguments)) {
        s += sep;
        s += '$name: ';
        s += _unmangleIfPreserved(
            runtimeTypeToString(JS('', '#[#]', _namedArguments, name)));
        sep = ', ';
      }
      s += '}';
    }
    s += ') -> ';
    if (_isVoid) {
      s += 'void';
    } else if (_hasReturnType) {
      s += _unmangleIfPreserved(runtimeTypeToString(_returnType));
    } else {
      s += 'dynamic';
    }
    return _cachedToString = "$s'";
  }

  bool isSubclassOf(ClassMirror other) => false;

  bool isSubtypeOf(TypeMirror other) => throw new UnimplementedError();

  bool isAssignableTo(TypeMirror other) => throw new UnimplementedError();

  // TODO(ahe): Implement this method.
  MethodMirror get callMethod => throw new UnimplementedError();
}

int findTypeVariableIndex(List<TypeVariableMirror> typeVariables, String name) {
  for (int i = 0; i < typeVariables.length; i++) {
    if (typeVariables[i].simpleName == s(name)) {
      return i;
    }
  }
  throw new ArgumentError('Type variable not present in list.');
}

TypeMirror typeMirrorFromRuntimeTypeRepresentation(
    DeclarationMirror owner,
    var /*int|List|JsFunction|TypeImpl*/ type) {
  // TODO(ahe): This method might benefit from using convertRtiToRuntimeType
  // instead of working on strings.
  ClassMirror ownerClass;
  DeclarationMirror context = owner;
  while (context != null) {
    if (context is ClassMirror) {
      ownerClass = context;
      break;
    }
    // TODO(ahe): Get type parameters and arguments from typedefs.
    if (context is TypedefMirror) break;
    context = context.owner;
  }

  String representation;
  if (type == null) {
    return JsMirrorSystem._dynamicType;
  } else if (type is TypeImpl) {
    return reflectType(type);
  } else if (ownerClass == null) {
    representation = runtimeTypeToString(type);
  } else if (ownerClass.isOriginalDeclaration) {
    if (type is num) {
      // [type] represents a type variable so in the context of an original
      // declaration the corresponding type variable should be returned.
      TypeVariable typeVariable = getMetadata(type);
      List<TypeVariableMirror> typeVariables = ownerClass.typeVariables;
      int index = findTypeVariableIndex(typeVariables, typeVariable.name);
      return typeVariables[index];
    } else {
      // Nested type variables will be retrieved lazily (the integer
      // representation is kept in the string) so they are not processed here.
      representation = runtimeTypeToString(type);
    }
  } else {
    TypeMirror getTypeArgument(int index) {
      TypeVariable typeVariable = getMetadata(index);
      int variableIndex =
          findTypeVariableIndex(ownerClass.typeVariables, typeVariable.name);
      return ownerClass.typeArguments[variableIndex];
    }

    if (type is num) {
      // [type] represents a type variable used as type argument for example
      // the type argument of Bar: class Foo<T> extends Bar<T> {}
      TypeMirror typeArgument = getTypeArgument(type);
      if (typeArgument is JsTypeVariableMirror)
        return typeArgument;
    }
    String substituteTypeVariable(int index) {
      var typeArgument = getTypeArgument(index);
      if (typeArgument is JsTypeVariableMirror) {
        return '${typeArgument._metadataIndex}';
      }
      if (typeArgument is! JsClassMirror &&
          typeArgument is! JsTypeBoundClassMirror) {
        if (typeArgument == JsMirrorSystem._dynamicType) {
          return 'dynamic';
        } else if (typeArgument == JsMirrorSystem._voidType) {
          return 'void';
        } else {
          // TODO(ahe): This case shouldn't happen.
          return 'dynamic';
        }
      }
      return typeArgument._mangledName;
    }
    representation =
        runtimeTypeToString(type, onTypeVariable: substituteTypeVariable);
  }
  if (representation != null) {
    return reflectClassByMangledName(
        getMangledTypeName(createRuntimeType(representation)));
  }
  String typedefPropertyName = JS_GET_NAME(JsGetName.TYPEDEF_TAG);
  if (type != null && JS('', '#[#]', type, typedefPropertyName) != null) {
    return typeMirrorFromRuntimeTypeRepresentation(
        owner, JS('', '#[#]', type, typedefPropertyName));
  } else if (type != null && isDartFunctionType(type)) {
    return new JsFunctionTypeMirror(type, owner);
  }
  return reflectClass(Function);
}

Symbol computeQualifiedName(DeclarationMirror owner, Symbol simpleName) {
  if (owner == null) return simpleName;
  String ownerName = n(owner.qualifiedName);
  return s('$ownerName.${n(simpleName)}');
}

List extractMetadata(victim) {
  preserveMetadata();
  var metadataFunction;
  if (JS('bool', 'Object.prototype.hasOwnProperty.call(#, "@")', victim)) {
    metadataFunction = JS('', '#["@"]', victim);
  }
  if (metadataFunction != null) return JS('', '#()', metadataFunction);
  if (JS('bool', 'typeof # != "function"', victim)) return const [];
  if (JS('bool', '# in #', r'$metadataIndex', victim)) {
    return JSArray.markFixedList(
        JS('JSExtendableArray',
           r'#.$reflectionInfo.splice(#.$metadataIndex)', victim, victim))
        .map((int i) => getMetadata(i)).toList();
  }
  return const [];
}

void parseCompactFieldSpecification(
    JsDeclarationMirror owner,
    fieldSpecification,
    bool isStatic,
    List<Mirror> result) {
  List fieldsMetadata = null;
  List<String> fields;
  if (fieldSpecification is List) {
    fields = splitFields(fieldSpecification[0], ',');
    fieldsMetadata = fieldSpecification.sublist(1);
  } else if (fieldSpecification is String) {
    fields = splitFields(fieldSpecification, ',');
  } else {
    fields = [];
  }
  int fieldNumber = 0;
  for (String field in fields) {
    var metadata;
    if (fieldsMetadata != null) {
      metadata = fieldsMetadata[fieldNumber++];
    }
    var mirror = new JsVariableMirror.from(field, metadata, owner, isStatic);
    if (mirror != null) {
      result.add(mirror);
    }
  }
}

/// Similar to [String.split], but returns an empty list if [string] is empty.
List<String> splitFields(String string, Pattern pattern) {
  if (string.isEmpty) return <String>[];
  return string.split(pattern);
}

bool isOperatorName(String name) {
  switch (name) {
  case '==':
  case '[]':
  case '*':
  case '/':
  case '%':
  case '~/':
  case '+':
  case '<<':
  case '>>':
  case '>=':
  case '>':
  case '<=':
  case '<':
  case '&':
  case '^':
  case '|':
  case '-':
  case 'unary-':
  case '[]=':
  case '~':
    return true;
  default:
    return false;
  }
}

/// Returns true if the key represent ancillary reflection data, that is, not a
/// method.
bool isReflectiveDataInPrototype(String key) {
  if (key == JS_GET_NAME(JsGetName.CLASS_DESCRIPTOR_PROPERTY) ||
      key == METHODS_WITH_OPTIONAL_ARGUMENTS) {
    return true;
  }
  String firstChar = key[0];
  return firstChar == '*' || firstChar == '+';
}

/// Returns `true` if [jsFunction] is an ordinary reflectable method and
/// not a (potentially reflectable) stub or otherwise non-reflectable method.
bool isOrdinaryReflectableMethod(var jsFunction) {
  return JS('bool', r'#.$reflectable === 1', jsFunction);
}

/// Returns true if [key] is only an aliased entry for [function] in the
/// prototype.
bool isAliasedSuperMethod(var jsFunction, String key) {
  var stubName = JS('String|Null', r'#.$stubName', jsFunction);
  return stubName != null && key != stubName;
}

class NoSuchStaticMethodError extends Error implements NoSuchMethodError {
  static const int MISSING_CONSTRUCTOR = 0;
  static const int MISSING_METHOD = 1;
  final ClassMirror _cls;
  final Symbol _name;
  final List _positionalArguments;
  final Map<Symbol, dynamic> _namedArguments;
  final int _kind;

  NoSuchStaticMethodError.missingConstructor(
      this._cls,
      this._name,
      this._positionalArguments,
      this._namedArguments)
      : _kind = MISSING_CONSTRUCTOR;

  /// If the given class is `null` the static method/getter/setter is top-level.
  NoSuchStaticMethodError.method(
      this._cls,
      this._name,
      this._positionalArguments,
      this._namedArguments)
      : _kind = MISSING_METHOD;

  String toString() {
    // TODO(floitsch): show arguments.
    switch(_kind) {
    case MISSING_CONSTRUCTOR:
      return
          "NoSuchMethodError: No constructor named '${n(_name)}' in class"
          " '${n(_cls.qualifiedName)}'.";
    case MISSING_METHOD:
      if (_cls == null) {
        return "NoSuchMethodError: No top-level method named '${n(_name)}'.";
      }
      return "NoSuchMethodError: No static method named '${n(_name)}' in"
             " class '${n(_cls.qualifiedName)}'";
    default:
      return 'NoSuchMethodError';
    }
  }
}

Symbol getSymbol(String name, LibraryMirror library) {
  if (_isPublicSymbol(name)) {
    return new _symbol_dev.Symbol.validated(name);
  }
  if (library == null) {
    throw new ArgumentError(
        "Library required for private symbol name: $name");
  }
  if (!_symbol_dev.Symbol.isValidSymbol(name)) {
    throw new ArgumentError("Not a valid symbol name: $name");
  }
  throw new UnimplementedError(
      "MirrorSystem.getSymbol not implemented for private names");
}

bool _isPublicSymbol(String name) {
  // A symbol is public if it doesn't start with '_' and it doesn't
  // have a part (following a '.') that starts with '_'.
  const int UNDERSCORE = 0x5f;
  if (name.isEmpty) return true;
  int index = -1;
  do {
    if (name.codeUnitAt(index + 1) == UNDERSCORE) return false;
    index = name.indexOf('.', index + 1);
  } while (index >= 0 && index + 1 < name.length);
  return true;
}
