// Copyright (c) 2012, 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.

part of html;

class _Property {
  _Property(this.name)
      : _hasValue = false,
        writable = false,
        isMethod = false,
        isOwn = true,
        wasThrown = false;

  bool get hasValue => _hasValue;
  get value => _value;
  set value(v) {
    _value = v;
    _hasValue = true;
  }

  final String name;
  Function setter;
  Function getter;
  var _value;
  bool _hasValue;
  bool writable;
  bool isMethod;
  bool isOwn;
  bool wasThrown;
}

/**
 * Manager for navigating between libraries from the devtools console.
 */
class _LibraryManager {
  /**
   * Current active library
   */
  static var _currentLibrary;
  static var _validCache = false;

  static List<Uri> _libraryUris;

  // List of all maps to check to determine if there is an exact match.
  static Map<String, List<Uri>> _fastPaths;

  static void _addFastPath(String key, Uri uri) {
    _fastPaths.putIfAbsent(key, () => <Uri>[]).add(uri);
  }

  static cache() {
    if (_validCache) return;
    _validCache = true;
    _libraryUris = <Uri>[];
    _fastPaths = new Map<String, List<Uri>>();
    var system = currentMirrorSystem();
    system.libraries.forEach((uri, library) {
      _libraryUris.add(uri);
      _addFastPath(uri.toString(), uri);
      _addFastPath(MirrorSystem.getName(library.simpleName), uri);
    });
  }

  static String get currentLibrary {
    if (_currentLibrary == null) {
      _currentLibrary =
          currentMirrorSystem().isolate.rootLibrary.uri.toString();
    }
    return _currentLibrary;
  }

  /**
   * Find libraries matching a given name.
   *
   * Uses heuristics to only return a single match when the user intent is
   * generally unambiguous.
   */
  static List<Uri> findMatches(String name) {
    cache();
    var nameAsFile = name.endsWith('.dart') ? name : '${name}.dart';
    // Perfect match first.
    var fastPatchMatches = _fastPaths[name];
    if (fastPatchMatches != null) {
      return fastPatchMatches.toList();
    }

    // Exact match for file path.
    var matches = new LinkedHashSet<Uri>();
    for (var uri in _libraryUris) {
      if (uri.path == name || uri.path == nameAsFile) matches.add(uri);
    }
    if (matches.isNotEmpty) return matches.toList();

    // Exact match for file name.
    if (name != nameAsFile) {
      for (var uri in _libraryUris) {
        if (uri.pathSegments.isNotEmpty &&
            (uri.pathSegments.last == nameAsFile)) {
          matches.add(uri);
        }
      }
      if (matches.isNotEmpty) return matches.toList();
    }

    for (var uri in _libraryUris) {
      if (uri.pathSegments.isNotEmpty && (uri.pathSegments.last == name)) {
        matches.add(uri);
      }
    }
    if (matches.isNotEmpty) return matches.toList();

    // Partial match on path.
    for (var uri in _libraryUris) {
      if (uri.path.contains(name)) {
        matches.add(uri);
      }
    }
    if (matches.isNotEmpty) return matches.toList();

    // Partial match on entire uri.
    for (var uri in _libraryUris) {
      if (uri.toString().contains(name)) {
        matches.add(uri);
      }
    }

    if (matches.isNotEmpty) return matches.toList();

    // Partial match on entire uri ignoring case.
    name = name.toLowerCase();
    for (var uri in _libraryUris) {
      if (uri.toString().toLowerCase().contains(name)) {
        matches.add(uri);
      }
    }
    return matches.toList();
  }

  static setLibrary([String? name]) {
    // Bust cache in case library list has changed. Ideally we would listen for
    // when libraries are loaded and invalidate based on that.
    _validCache = false;
    cache();
    if (name == null) {
      window.console
        ..group("Current library: $_currentLibrary")
        ..groupCollapsed("All libraries:");
      _listLibraries();
      window.console..groupEnd()..groupEnd();
      return;
    }
    var matches = findMatches(name);
    if (matches.length != 1) {
      if (matches.length > 1) {
        window.console.warn("Ambiguous library name: $name");
      }
      showMatches(name, matches);
      return;
    }
    _currentLibrary = matches.first.toString();
    window.console.log("Set library to $_currentLibrary");
  }

  static getLibrary() {
    return currentLibrary;
  }

  static List<Uri> _sortUris(Iterable<Uri> uris) {
    return (uris.toList())
      ..sort((Uri a, Uri b) {
        if (a.scheme != b.scheme) {
          if (a.scheme == 'dart') return -1;
          if (b.scheme == 'dart') return 1;
          return a.scheme.compareTo(b.scheme);
        }
        return a.toString().compareTo(b.toString());
      });
  }

  static void listLibraries() {
    _validCache = false;
    cache();
    _listLibraries();
  }

  static void _listLibraries() {
    window.console.log(_sortUris(_libraryUris).join("\n"));
  }

  // Workaround to allow calling console.log with an arbitrary number of
  // arguments.
  static void _log(List<String> args) {
    js.JsNative.callMethod(window.console, 'log', args);
  }

  static showMatches(String key, Iterable<Uri> uris) {
    var boldPairs = [];
    var sb = new StringBuffer();
    if (uris.isEmpty) {
      window.console.group("All libraries:");
      _listLibraries();
      window.console
        ..groupEnd()
        ..error("No library names or URIs match '$key'");
      return;
    }
    sb.write("${uris.length} matches\n");
    var lowerCaseKey = key.toLowerCase();
    for (var uri in uris) {
      var txt = uri.toString();
      int index = txt.toLowerCase().indexOf(lowerCaseKey);
      if (index != -1) {
        // %c enables styling console log messages with css
        // specified at the end of the console.
        sb..write(txt.substring(0, index))..write('%c');
        var matchEnd = index + key.length;
        sb
          ..write(txt.substring(index, matchEnd))
          ..write('%c')
          ..write(txt.substring(matchEnd))
          ..write('\n');
        boldPairs..add('font-weight: bold')..add('font-weight: normal');
      }
    }
    _log([sb.toString()]..addAll(boldPairs));
  }
}

class _ConsoleVariables {
  Map<String, Object> _data = new Map<String, Object>();

  /**
   * Forward member accesses to the backing JavaScript object.
   */
  noSuchMethod(Invocation invocation) {
    String member = MirrorSystem.getName(invocation.memberName);
    if (invocation.isGetter) {
      return _data[member];
    } else if (invocation.isSetter) {
      assert(member.endsWith('='));
      member = member.substring(0, member.length - 1);
      _data[member] = invocation.positionalArguments[0];
    } else {
      return Function.apply(_data[member], invocation.positionalArguments,
          invocation.namedArguments);
    }
  }

  void clear() => _data.clear();

  /**
   * List all variables currently defined.
   */
  List variables() => _data.keys.toList();

  void setVariable(String name, value) {
    _data[name] = value;
  }
}

/**
 * Base class for invocation trampolines used to closurize methods, getters
 * and setters.
 */
abstract class _Trampoline implements Function {
  final ObjectMirror _receiver;
  final MethodMirror _methodMirror;
  final Symbol _selector;

  _Trampoline(this._receiver, this._methodMirror, this._selector);
}

class _MethodTrampoline extends _Trampoline {
  _MethodTrampoline(
      ObjectMirror receiver, MethodMirror methodMirror, Symbol selector)
      : super(receiver, methodMirror, selector);

  noSuchMethod(Invocation msg) {
    if (msg.memberName != #call) return super.noSuchMethod(msg);
    return _receiver
        .invoke(_selector, msg.positionalArguments, msg.namedArguments)
        .reflectee;
  }
}

/**
 * Invocation trampoline class used to closurize getters.
 */
class _GetterTrampoline extends _Trampoline {
  _GetterTrampoline(
      ObjectMirror receiver, MethodMirror methodMirror, Symbol selector)
      : super(receiver, methodMirror, selector);

  call() => _receiver.getField(_selector).reflectee;
}

/**
 * Invocation trampoline class used to closurize setters.
 */
class _SetterTrampoline extends _Trampoline {
  _SetterTrampoline(
      ObjectMirror receiver, MethodMirror methodMirror, Symbol selector)
      : super(receiver, methodMirror, selector);

  call(value) {
    _receiver.setField(_selector, value);
  }
}

class _Utils {
  static double dateTimeToDouble(DateTime dateTime) =>
      dateTime.millisecondsSinceEpoch.toDouble();
  static DateTime doubleToDateTime(double dateTime) {
    try {
      return new DateTime.fromMillisecondsSinceEpoch(dateTime.toInt());
    } catch (_) {
      // TODO(antonnm): treat exceptions properly in bindings and
      // find out how to treat NaNs.
      return null;
    }
  }

  static List convertToList(List list) {
    // FIXME: [possible optimization]: do not copy the array if Dart_IsArray is fine w/ it.
    final length = list.length;
    List result = new List(length);
    result.setRange(0, length, list);
    return result;
  }

  static List convertMapToList(Map map) {
    List result = [];
    map.forEach((k, v) => result.addAll([k, v]));
    return result;
  }

  static int convertCanvasElementGetContextMap(Map map) {
    int result = 0;
    if (map['alpha'] == true) result |= 0x01;
    if (map['depth'] == true) result |= 0x02;
    if (map['stencil'] == true) result |= 0x4;
    if (map['antialias'] == true) result |= 0x08;
    if (map['premultipliedAlpha'] == true) result |= 0x10;
    if (map['preserveDrawingBuffer'] == true) result |= 0x20;

    return result;
  }

  static void populateMap(Map result, List list) {
    for (int i = 0; i < list.length; i += 2) {
      result[list[i]] = list[i + 1];
    }
  }

  static bool isMap(obj) => obj is Map;

  static List toListIfIterable(obj) => obj is Iterable ? obj.toList() : null;

  static Map createMap() => {};

  static parseJson(String jsonSource) =>
      const JsonDecoder().convert(jsonSource);

  static String getLibraryUrl() => _LibraryManager.currentLibrary;

  static makeUnimplementedError(String fileName, int lineNo) {
    return new UnsupportedError('[info: $fileName:$lineNo]');
  }

  static bool isTypeSubclassOf(Type type, Type other) {
    if (type == other) {
      return true;
    }
    var superclass = reflectClass(type).superclass;
    if (superclass != null) {
      return isTypeSubclassOf(superclass.reflectedType, other);
    }
    return false;
  }

  static Element getAndValidateNativeType(Type type, String tagName) {
    var element = new Element.tag(tagName);
    if (!isTypeSubclassOf(type, element.runtimeType)) {
      return null;
    }
    return element;
  }

  static forwardingPrint(String message) =>
      _blink.Blink_Utils.forwardingPrint(message);
  static void spawnDomHelper(Function f, int replyTo) =>
      _blink.Blink_Utils.spawnDomHelper(f, replyTo);

  // TODO(vsm): Make this API compatible with spawnUri.  It should also
  // return a Future<Isolate>.
  // TODO(jacobr): IS THIS RIGHT? I worry we have broken conversion from Promise to Future.
  static spawnDomUri(String uri) => _blink.Blink_Utils.spawnDomUri(uri);

  // The following methods were added for debugger integration to make working
  // with the Dart C mirrors API simpler.
  // TODO(jacobr): consider moving them to a separate library.
  // If Dart supported dynamic code injection, we would only inject this code
  // when the debugger is invoked.

  /**
   * Strips the private secret prefix from member names of the form
   * someName@hash.
   */
  static String stripMemberName(String name) {
    int endIndex = name.indexOf('@');
    return endIndex > 0 ? name.substring(0, endIndex) : name;
  }

  /**
   * Takes a list containing variable names and corresponding values and
   * returns a map from normalized names to values. Variable names are assumed
   * to have list offsets 2*n values at offset 2*n+1. This method is required
   * because Dart_GetLocalVariables returns a list instead of an object that
   * can be queried to lookup names and values.
   */
  static Map<String, dynamic> createLocalVariablesMap(List localVariables) {
    var map = {};
    for (int i = 0; i < localVariables.length; i += 2) {
      map[stripMemberName(localVariables[i])] = localVariables[i + 1];
    }
    return map;
  }

  static _ConsoleVariables _consoleTempVariables = new _ConsoleVariables();

  /**
   * Takes an [expression] and a list of [local] variable and returns an
   * expression for a closure with a body matching the original expression
   * where locals are passed in as arguments. Returns a list containing the
   * String expression for the closure and the list of arguments that should
   * be passed to it. The expression should then be evaluated using
   * Dart_EvaluateExpr which will generate a closure that should be invoked
   * with the list of arguments passed to this method.
   *
   * For example:
   * <code>
   * _consoleTempVariables = {'a' : someValue, 'b': someOtherValue}
   * wrapExpressionAsClosure("foo + bar + a", ["bar", 40, "foo", 2], true)
   * </code>
   * will return:
   * <code>
   * ["""(final $consoleVariables, final bar, final foo, final a, final b) =>
   * (foo + bar + a
   * )""",
   * [_consoleTempVariables, 40, 2, someValue, someOtherValue]]
   * </code>
   */
  static List wrapExpressionAsClosure(
      String expression, List locals, bool includeCommandLineAPI) {
    var args = {};
    var sb = new StringBuffer("(");
    addArg(arg, value) {
      arg = stripMemberName(arg);
      if (args.containsKey(arg)) return;
      // We ignore arguments with the name 'this' rather than throwing an
      // exception because Dart_GetLocalVariables includes 'this' and it
      // is more convenient to filter it out here than from C++ code.
      // 'this' needs to be handled by calling Dart_EvaluateExpr with
      // 'this' as the target rather than by passing it as an argument.
      if (arg == 'this') return;
      // Avoid being broken by bogus ':async_op' local passed in when within
      // an async method.
      if (arg.startsWith(':')) return;
      if (args.isNotEmpty) {
        sb.write(", ");
      }
      sb.write("final $arg");
      args[arg] = value;
    }

    if (includeCommandLineAPI) {
      addArg("\$consoleVariables", _consoleTempVariables);

      // FIXME: use a real Dart tokenizer. The following regular expressions
      // only allow setting variables at the immediate start of the expression
      // to limit the number of edge cases we have to handle.

      // Match expressions that start with "var x"
      final _VARIABLE_DECLARATION = new RegExp("^(\\s*)var\\s+(\\w+)");
      // Match expressions that start with "someExistingConsoleVar ="
      final _SET_VARIABLE = new RegExp("^(\\s*)(\\w+)(\\s*=)");
      // Match trailing semicolons.
      final _ENDING_SEMICOLONS = new RegExp("(;\\s*)*\$");
      expression = expression.replaceAllMapped(_VARIABLE_DECLARATION, (match) {
        var variableName = match[2];
        // Set the console variable if it isn't already set.
        if (!_consoleTempVariables._data.containsKey(variableName)) {
          _consoleTempVariables._data[variableName] = null;
        }
        return "${match[1]}\$consoleVariables.${variableName}";
      });

      expression = expression.replaceAllMapped(_SET_VARIABLE, (match) {
        var variableName = match[2];
        // Only rewrite if the name matches an existing console variable.
        if (_consoleTempVariables._data.containsKey(variableName)) {
          return "${match[1]}\$consoleVariables.${variableName}${match[3]}";
        } else {
          return match[0];
        }
      });

      // We only allow dart expressions not Dart statements. Silently remove
      // trailing semicolons the user might have added by accident to reduce the
      // number of spurious compile errors.
      expression = expression.replaceFirst(_ENDING_SEMICOLONS, "");
    }

    if (locals != null) {
      for (int i = 0; i < locals.length; i += 2) {
        addArg(locals[i], locals[i + 1]);
      }
    }
    // Inject all the already defined console variables.
    _consoleTempVariables._data.forEach(addArg);

    // TODO(jacobr): remove the parentheses around the expression once
    // dartbug.com/13723 is fixed. Currently we wrap expression in parentheses
    // to ensure only valid Dart expressions are allowed. Otherwise the DartVM
    // quietly ignores trailing Dart statements resulting in user confusion
    // when part of an invalid expression they entered is ignored.
    sb..write(') => (\n$expression\n)');
    return [sb.toString(), args.values.toList(growable: false)];
  }

  static String _getShortSymbolName(
      Symbol symbol, DeclarationMirror declaration) {
    var name = MirrorSystem.getName(symbol);
    if (declaration is MethodMirror) {
      if (declaration.isSetter && name[name.length - 1] == "=") {
        return name.substring(0, name.length - 1);
      }
      if (declaration.isConstructor) {
        return name.substring(name.indexOf('.') + 1);
      }
    }
    return name;
  }

  /**
   * Handle special console commands such as $lib and $libs that should not be
   * evaluated as Dart expressions and instead should be interpreted directly.
   * Commands supported:
   * library <-- shows the current library and lists all libraries.
   * library "library_uri" <-- select a specific library
   * library "library_uri_fragment"
   */
  static bool maybeHandleSpecialConsoleCommand(String expression) {
    expression = expression.trim();
    var setLibraryCommand = r'library ';
    if (expression == r'library') {
      _LibraryManager.setLibrary();
      return true;
    }
    if (expression.startsWith(setLibraryCommand)) {
      expression = expression.substring(setLibraryCommand.length);
      if (expression.length >= 2) {
        String start = expression[0];
        String end = expression[expression.length - 1];
        // TODO(jacobr): maybe we should require quotes.
        if ((start == "'" && end == "'") || (start == '"' && end == '"')) {
          expression = expression.substring(1, expression.length - 1);
        }
      }

      _LibraryManager.setLibrary(expression);
      return true;
    }
    return false;
  }

  /**
   * Returns a list of completions to use if the receiver is o.
   */
  static List<String> getCompletions(o) {
    MirrorSystem system = currentMirrorSystem();
    var completions = new Set<String>();
    addAll(Map<Symbol, dynamic> map, bool isStatic) {
      map.forEach((symbol, mirror) {
        if (mirror.isStatic == isStatic && !mirror.isPrivate) {
          var name = MirrorSystem.getName(symbol);
          if (mirror is MethodMirror && mirror.isSetter)
            name = name.substring(0, name.length - 1);
          completions.add(name);
        }
      });
    }

    addForClass(ClassMirror mirror, bool isStatic) {
      if (mirror == null) return;
      addAll(mirror.declarations, isStatic);
      if (mirror.superclass != null) addForClass(mirror.superclass, isStatic);
      for (var interface in mirror.superinterfaces) {
        addForClass(interface, isStatic);
      }
    }

    if (o is Type) {
      addForClass(reflectClass(o), true);
    } else {
      addForClass(reflect(o).type, false);
    }
    return completions.toList(growable: false);
  }

  /**
   * Adds all candidate String completions from [declarations] to [output]
   * filtering based on [staticContext] and [includePrivate].
   */
  static void _getCompletionsHelper(ClassMirror classMirror, bool staticContext,
      LibraryMirror libraryMirror, Set<String> output) {
    bool includePrivate = libraryMirror == classMirror.owner;
    classMirror.declarations.forEach((symbol, declaration) {
      if (!includePrivate && declaration.isPrivate) return;
      if (declaration is VariableMirror) {
        if (staticContext != declaration.isStatic) return;
      } else if (declaration is MethodMirror) {
        if (declaration.isOperator) return;
        if (declaration.isConstructor) {
          if (!staticContext) return;
          var name = MirrorSystem.getName(declaration.constructorName);
          if (name.isNotEmpty) output.add(name);
          return;
        }
        if (staticContext != declaration.isStatic) return;
      } else if (declaration is TypeMirror) {
        return;
      }
      output.add(_getShortSymbolName(symbol, declaration));
    });

    if (!staticContext) {
      for (var interface in classMirror.superinterfaces) {
        _getCompletionsHelper(interface, staticContext, libraryMirror, output);
      }
      if (classMirror.superclass != null) {
        _getCompletionsHelper(
            classMirror.superclass, staticContext, libraryMirror, output);
      }
    }
  }

  static void _getLibraryCompletionsHelper(
      LibraryMirror library, bool includePrivate, Set<String> output) {
    library.declarations.forEach((symbol, declaration) {
      if (!includePrivate && declaration.isPrivate) return;
      output.add(_getShortSymbolName(symbol, declaration));
    });
  }

  static LibraryMirror getLibraryMirror(String url) =>
      currentMirrorSystem().libraries[Uri.parse(url)];

  /**
   * Get code completions for [o] only showing privates from [libraryUrl].
   */
  static List<String> getObjectCompletions(o, String libraryUrl) {
    var classMirror;
    bool staticContext;
    if (o is Type) {
      classMirror = reflectClass(o);
      staticContext = true;
    } else {
      classMirror = reflect(o).type;
      staticContext = false;
    }
    var names = new Set<String>();
    getClassCompletions(classMirror, names, staticContext, libraryUrl);
    return names.toList()..sort();
  }

  static void getClassCompletions(ClassMirror classMirror, Set<String> names,
      bool staticContext, String libraryUrl) {
    LibraryMirror libraryMirror = getLibraryMirror(libraryUrl);
    _getCompletionsHelper(classMirror, staticContext, libraryMirror, names);
  }

  static List<String> getLibraryCompletions(String url) {
    var names = new Set<String>();
    _getLibraryCompletionsHelper(getLibraryMirror(url), true, names);
    return names.toList();
  }

  /**
   * Get valid code completions from within a library and all libraries
   * imported by that library.
   */
  static List<String> getLibraryCompletionsIncludingImports(String url) {
    var names = new Set<String>();
    var libraryMirror = getLibraryMirror(url);
    _getLibraryCompletionsHelper(libraryMirror, true, names);
    for (var dependency in libraryMirror.libraryDependencies) {
      if (dependency.isImport) {
        if (dependency.prefix == null) {
          _getLibraryCompletionsHelper(dependency.targetLibrary, false, names);
        } else {
          names.add(MirrorSystem.getName(dependency.prefix));
        }
      }
    }
    return names.toList();
  }

  static final SIDE_EFFECT_FREE_LIBRARIES = new Set<String>()
    ..add('dart:html')
    ..add('dart:indexed_db')
    ..add('dart:svg')
    ..add('dart:typed_data')
    ..add('dart:web_audio')
    ..add('dart:web_gl')
    ..add('dart:web_sql');

  static LibraryMirror _getLibrary(MethodMirror methodMirror) {
    var owner = methodMirror.owner;
    if (owner is ClassMirror) {
      return owner;
    } else if (owner is LibraryMirror) {
      return owner;
    }
    return null;
  }

  /**
   * For parity with the JavaScript debugger, we treat some getters as if
   * they are fields so that users can see their values immediately.
   * This matches JavaScript's behavior for getters on DOM objects.
   * In the future we should consider adding an annotation to tag getters
   * in user libraries as side effect free.
   */
  static bool _isSideEffectFreeGetter(
      MethodMirror methodMirror, LibraryMirror libraryMirror) {
    // This matches JavaScript behavior. We should consider displaying
    // getters for all dart platform libraries rather than just the DOM
    // libraries.
    return libraryMirror.uri.scheme == 'dart' &&
        SIDE_EFFECT_FREE_LIBRARIES.contains(libraryMirror.uri.toString());
  }

  /**
   * Whether we should treat a property as a field for the purposes of the
   * debugger.
   */
  static bool treatPropertyAsField(
      MethodMirror methodMirror, LibraryMirror libraryMirror) {
    return (methodMirror.isGetter || methodMirror.isSetter) &&
        (methodMirror.isSynthetic ||
            _isSideEffectFreeGetter(methodMirror, libraryMirror));
  }

  // TODO(jacobr): generate more concise function descriptions instead of
  // dumping the entire function source.
  static String describeFunction(function) {
    if (function is _Trampoline) return function._methodMirror.source;
    try {
      var mirror = reflect(function);
      return mirror.function.source;
    } catch (e) {
      return function.toString();
    }
  }

  static List getInvocationTrampolineDetails(_Trampoline method) {
    var loc = method._methodMirror.location;
    return [
      loc.line,
      loc.column,
      loc.sourceUri.toString(),
      MirrorSystem.getName(method._selector)
    ];
  }

  static List getLibraryProperties(
      String libraryUrl, bool ownProperties, bool accessorPropertiesOnly) {
    var properties = new Map<String, _Property>();
    var libraryMirror = getLibraryMirror(libraryUrl);
    _addInstanceMirrors(
        libraryMirror,
        libraryMirror,
        libraryMirror.declarations,
        ownProperties,
        accessorPropertiesOnly,
        false,
        false,
        properties);
    if (!accessorPropertiesOnly) {
      // We need to add class properties for all classes in the library.
      libraryMirror.declarations.forEach((symbol, declarationMirror) {
        if (declarationMirror is ClassMirror) {
          var name = MirrorSystem.getName(symbol);
          if (declarationMirror.hasReflectedType &&
              !properties.containsKey(name)) {
            properties[name] = new _Property(name)
              ..value = declarationMirror.reflectedType;
          }
        }
      });
    }
    return packageProperties(properties);
  }

  static List getObjectProperties(
      o, bool ownProperties, bool accessorPropertiesOnly) {
    var properties = new Map<String, _Property>();
    var names = new Set<String>();
    var objectMirror = reflect(o);
    var classMirror = objectMirror.type;
    _addInstanceMirrors(
        objectMirror,
        classMirror.owner,
        classMirror.instanceMembers,
        ownProperties,
        accessorPropertiesOnly,
        false,
        true,
        properties);
    return packageProperties(properties);
  }

  static List getObjectClassProperties(
      o, bool ownProperties, bool accessorPropertiesOnly) {
    var properties = new Map<String, _Property>();
    var objectMirror = reflect(o);
    var classMirror = objectMirror.type;
    _addInstanceMirrors(
        objectMirror,
        classMirror.owner,
        classMirror.instanceMembers,
        ownProperties,
        accessorPropertiesOnly,
        true,
        false,
        properties);
    _addStatics(classMirror, properties, accessorPropertiesOnly);
    return packageProperties(properties);
  }

  static List getClassProperties(
      Type t, bool ownProperties, bool accessorPropertiesOnly) {
    var properties = new Map<String, _Property>();
    var classMirror = reflectClass(t);
    _addStatics(classMirror, properties, accessorPropertiesOnly);
    return packageProperties(properties);
  }

  static void _addStatics(ClassMirror classMirror,
      Map<String, _Property> properties, bool accessorPropertiesOnly) {
    var libraryMirror = classMirror.owner;
    classMirror.declarations.forEach((symbol, declaration) {
      var name = _getShortSymbolName(symbol, declaration);
      if (name.isEmpty) return;
      if (declaration is VariableMirror) {
        if (accessorPropertiesOnly) return;
        if (!declaration.isStatic) return;
        properties.putIfAbsent(name, () => new _Property(name))
          ..value = classMirror.getField(symbol).reflectee
          ..writable = !declaration.isFinal && !declaration.isConst;
      } else if (declaration is MethodMirror) {
        MethodMirror methodMirror = declaration;
        // FIXMEDART: should we display constructors?
        if (methodMirror.isConstructor) return;
        if (!methodMirror.isStatic) return;
        if (accessorPropertiesOnly) {
          if (methodMirror.isRegularMethod ||
              treatPropertyAsField(methodMirror, libraryMirror)) {
            return;
          }
        } else if (!methodMirror.isRegularMethod &&
            !treatPropertyAsField(methodMirror, libraryMirror)) {
          return;
        }
        var property = properties.putIfAbsent(name, () => new _Property(name));
        _fillMethodMirrorProperty(libraryMirror, classMirror, methodMirror,
            symbol, accessorPropertiesOnly, property);
      }
    });
  }

  static void _fillMethodMirrorProperty(
      LibraryMirror libraryMirror,
      methodOwner,
      MethodMirror methodMirror,
      Symbol symbol,
      bool accessorPropertiesOnly,
      _Property property) {
    if (methodMirror.isRegularMethod) {
      property
        ..value = new _MethodTrampoline(methodOwner, methodMirror, symbol)
        ..isMethod = true;
    } else if (methodMirror.isGetter) {
      if (treatPropertyAsField(methodMirror, libraryMirror)) {
        try {
          property.value = methodOwner.getField(symbol).reflectee;
        } catch (e) {
          property
            ..wasThrown = true
            ..value = e;
        }
      } else if (accessorPropertiesOnly) {
        property.getter =
            new _GetterTrampoline(methodOwner, methodMirror, symbol);
      }
    } else if (methodMirror.isSetter) {
      if (accessorPropertiesOnly &&
          !treatPropertyAsField(methodMirror, libraryMirror)) {
        property.setter = new _SetterTrampoline(methodOwner, methodMirror,
            MirrorSystem.getSymbol(property.name, libraryMirror));
      }
      property.writable = true;
    }
  }

  /**
   * Helper method that handles collecting up properties from classes
   * or libraries using the filters [ownProperties], [accessorPropertiesOnly],
   * [hideFields], and [hideMethods] to determine which properties are
   * collected. [accessorPropertiesOnly] specifies whether all properties
   * should be returned or just accessors. [hideFields] specifies whether
   * fields should be hidden. hideMethods specifies whether methods should be
   * shown or hidden. [ownProperties] is not currently used but is part of the
   * Blink devtools API for enumerating properties.
   */
  static void _addInstanceMirrors(
      ObjectMirror objectMirror,
      LibraryMirror libraryMirror,
      Map<Symbol, Mirror> declarations,
      bool ownProperties,
      bool accessorPropertiesOnly,
      bool hideFields,
      bool hideMethods,
      Map<String, _Property> properties) {
    declarations.forEach((symbol, declaration) {
      if (declaration is TypedefMirror || declaration is ClassMirror) return;
      var name = _getShortSymbolName(symbol, declaration);
      if (name.isEmpty) return;
      bool isField = declaration is VariableMirror ||
          (declaration is MethodMirror &&
              treatPropertyAsField(declaration, libraryMirror));
      if ((isField && hideFields) || (hideMethods && !isField)) return;
      if (accessorPropertiesOnly) {
        if (declaration is VariableMirror ||
            declaration.isRegularMethod ||
            isField) {
          return;
        }
      } else if (declaration is MethodMirror &&
          (declaration.isGetter || declaration.isSetter) &&
          !treatPropertyAsField(declaration, libraryMirror)) {
        return;
      }
      var property = properties.putIfAbsent(name, () => new _Property(name));
      if (declaration is VariableMirror) {
        property
          ..value = objectMirror.getField(symbol).reflectee
          ..writable = !declaration.isFinal && !declaration.isConst;
        return;
      }
      _fillMethodMirrorProperty(libraryMirror, objectMirror, declaration,
          symbol, accessorPropertiesOnly, property);
    });
  }

  /**
   * Flatten down the properties data structure into a List that is easy to
   * access from native code.
   */
  static List packageProperties(Map<String, _Property> properties) {
    var ret = [];
    for (var property in properties.values) {
      ret.addAll([
        property.name,
        property.setter,
        property.getter,
        property.value,
        property.hasValue,
        property.writable,
        property.isMethod,
        property.isOwn,
        property.wasThrown
      ]);
    }
    return ret;
  }

  /**
   * Get a property, returning null if the property does not exist.
   * For private property names, we attempt to resolve the property in the
   * context of each library that the property name could be associated with.
   */
  static getObjectPropertySafe(o, String propertyName) {
    var objectMirror = reflect(o);
    var classMirror = objectMirror.type;
    if (propertyName.startsWith("_")) {
      var attemptedLibraries = new Set<LibraryMirror>();
      while (classMirror != null) {
        LibraryMirror library = classMirror.owner;
        if (!attemptedLibraries.contains(library)) {
          try {
            return objectMirror
                .getField(MirrorSystem.getSymbol(propertyName, library))
                .reflectee;
          } catch (e) {}
          attemptedLibraries.add(library);
        }
        classMirror = classMirror.superclass;
      }
      return null;
    }
    try {
      return objectMirror
          .getField(MirrorSystem.getSymbol(propertyName))
          .reflectee;
    } catch (e) {
      return null;
    }
  }

  /**
   * Helper to wrap the inspect method on InjectedScriptHost to provide the
   * inspect method required for the
   */
  static List consoleApi(host) {
    return [
      "inspect",
      (o) {
        js.JsNative.callMethod(host, "_inspect", [o]);
        return o;
      },
      "dir",
      window.console.dir,
      "dirxml",
      window.console.dirxml
      // FIXME: add copy method.
    ];
  }

  static List getMapKeyList(Map map) => map.keys.toList();

  static bool isNoSuchMethodError(obj) => obj is NoSuchMethodError;

  static void register(
      Document document, String tag, Type type, String extendsTagName) {
    var nativeClass = _validateCustomType(type);

    if (extendsTagName == null) {
      if (nativeClass.reflectedType != HtmlElement) {
        throw new UnsupportedError('Class must provide extendsTag if base '
            'native class is not HTMLElement');
      }
    }

    _register(document, tag, type, extendsTagName);
  }

  static void _register(Document document, String tag, Type customType,
          String extendsTagName) =>
      _blink.Blink_Utils.register(document, tag, customType, extendsTagName);

  static Element createElement(Document document, String tagName) =>
      _blink.Blink_Utils.createElement(document, tagName);
}

class _DOMWindowCrossFrame extends DartHtmlDomObject implements WindowBase {
  _DOMWindowCrossFrame.internal();

  static _createSafe(win) {
    if (identical(win, window)) {
      // The current Window object is the only window object that should not
      // use _DOMWindowCrossFrame.
      return window;
    }
    return win is _DOMWindowCrossFrame
        ? win
        : _blink.Blink_Utils.setInstanceInterceptor(win, _DOMWindowCrossFrame);
  }

  // Fields.
  HistoryBase get history {
    var history = _blink.BlinkWindow.instance.history_Getter_(this);
    return history is _HistoryCrossFrame
        ? history
        : _blink.Blink_Utils.setInstanceInterceptor(
            history, _HistoryCrossFrame);
  }

  LocationBase get location {
    var location = _blink.BlinkWindow.instance.location_Getter_(this);
    return location is _LocationCrossFrame
        ? location
        : _blink.Blink_Utils.setInstanceInterceptor(
            location, _LocationCrossFrame);
  }

  bool get closed => _blink.BlinkWindow.instance.closed_Getter_(this);
  WindowBase get opener => _convertNativeToDart_Window(
      _blink.BlinkWindow.instance.opener_Getter_(this));
  WindowBase get parent => _convertNativeToDart_Window(
      _blink.BlinkWindow.instance.parent_Getter_(this));
  WindowBase get top => _convertNativeToDart_Window(
      _blink.BlinkWindow.instance.top_Getter_(this));

  // Methods.
  void close() => _blink.BlinkWindow.instance.close_Callback_0_(this);
  void postMessage(Object message, String targetOrigin,
          [List<MessagePort>? transfer]) =>
      _blink.BlinkWindow.instance.postMessage_Callback_3_(
          this,
          convertDartToNative_SerializedScriptValue(message),
          targetOrigin,
          transfer);

  // Implementation support.
  String get typeName => "Window";

  // TODO(efortuna): Remove this method. dartbug.com/16814
  Events get on => throw new UnsupportedError(
      'You can only attach EventListeners to your own window.');
  // TODO(efortuna): Remove this method. dartbug.com/16814
  void _addEventListener(
          [String? type, EventListener? listener, bool? useCapture]) =>
      throw new UnsupportedError(
          'You can only attach EventListeners to your own window.');
  // TODO(efortuna): Remove this method. dartbug.com/16814
  void addEventListener(String type, EventListener? listener,
          [bool? useCapture]) =>
      throw new UnsupportedError(
          'You can only attach EventListeners to your own window.');
  // TODO(efortuna): Remove this method. dartbug.com/16814
  bool dispatchEvent(Event event) => throw new UnsupportedError(
      'You can only attach EventListeners to your own window.');
  // TODO(efortuna): Remove this method. dartbug.com/16814
  void _removeEventListener(
          [String? type, EventListener? listener, bool? useCapture]) =>
      throw new UnsupportedError(
          'You can only attach EventListeners to your own window.');
  // TODO(efortuna): Remove this method. dartbug.com/16814
  void removeEventListener(String type, EventListener? listener,
          [bool? useCapture]) =>
      throw new UnsupportedError(
          'You can only attach EventListeners to your own window.');
}

class _HistoryCrossFrame extends DartHtmlDomObject implements HistoryBase {
  _HistoryCrossFrame.internal();

  // Methods.
  void back() => _blink.BlinkHistory.instance.back_Callback_0_(this);
  void forward() => _blink.BlinkHistory.instance.forward_Callback_0_(this);
  void go([int? delta]) {
    if (delta != null) {
      _blink.BlinkHistory.instance.go_Callback_1_(this, delta);
      return;
    }
    _blink.BlinkHistory.instance.go_Callback_0_(this);
    return;
  }

  // Implementation support.
  String get typeName => "History";
}

class _LocationCrossFrame extends DartHtmlDomObject implements LocationBase {
  _LocationCrossFrame.internal();

  // Fields.
  set href(String value) =>
      _blink.BlinkLocation.instance.href_Setter_(this, value);

  // Implementation support.
  String get typeName => "Location";
}

// TODO(vsm): Remove DOM isolate code once we have Dartium isolates
// as workers.  This is only used to support
// printing and timers in background isolates. As workers they should
// be able to just do those things natively.

_makeSendPortFuture(spawnRequest) {
  final completer = new Completer<SendPort>.sync();
  final port = new ReceivePort();
  port.listen((result) {
    completer.complete(result);
    port.close();
  });
  // TODO: SendPort.hashCode is ugly way to access port id.
  spawnRequest(port.sendPort.hashCode);
  return completer.future;
}

Future<SendPort> _spawnDomHelper(Function f) => _makeSendPortFuture((portId) {
      _Utils.spawnDomHelper(f, portId);
    });

final Future<SendPort> __HELPER_ISOLATE_PORT =
    _spawnDomHelper(_helperIsolateMain);

// Tricky part.
// Once __HELPER_ISOLATE_PORT gets resolved, it will still delay in .then
// and to delay Timer.run is used. However, Timer.run will try to register
// another Timer and here we got stuck: event cannot be posted as then
// callback is not executed because it's delayed with timer.
// Therefore once future is resolved, it's unsafe to call .then on it
// in Timer code.
SendPort __SEND_PORT;

_sendToHelperIsolate(msg, SendPort replyTo) {
  if (__SEND_PORT != null) {
    __SEND_PORT.send([msg, replyTo]);
  } else {
    __HELPER_ISOLATE_PORT.then((port) {
      __SEND_PORT = port;
      __SEND_PORT.send([msg, replyTo]);
    });
  }
}

final _TIMER_REGISTRY = new Map<SendPort, Timer>();

const _NEW_TIMER = 'NEW_TIMER';
const _CANCEL_TIMER = 'CANCEL_TIMER';
const _TIMER_PING = 'TIMER_PING';
const _PRINT = 'PRINT';

_helperIsolateMain(originalSendPort) {
  var port = new ReceivePort();
  originalSendPort.send(port.sendPort);
  port.listen((args) {
    var msg = args.first;
    var replyTo = args.last;
    final cmd = msg[0];
    if (cmd == _NEW_TIMER) {
      final duration = new Duration(milliseconds: msg[1]);
      bool periodic = msg[2];
      ping() {
        replyTo.send(_TIMER_PING);
      }

      ;
      _TIMER_REGISTRY[replyTo] = periodic
          ? new Timer.periodic(duration, (_) {
              ping();
            })
          : new Timer(duration, ping);
    } else if (cmd == _CANCEL_TIMER) {
      _TIMER_REGISTRY.remove(replyTo).cancel();
    } else if (cmd == _PRINT) {
      final message = msg[1];
      // TODO(antonm): we need somehow identify those isolates.
      print('[From isolate] $message');
    }
  });
}

final _printClosure = (s) => window.console.log(s);
final _pureIsolatePrintClosure = (s) {
  _sendToHelperIsolate([_PRINT, s], null);
};

final _forwardingPrintClosure = _Utils.forwardingPrint;

final _uriBaseClosure = () => Uri.parse(window.location.href);

final _pureIsolateUriBaseClosure = () {
  throw new UnimplementedError("Uri.base on a background isolate "
      "is not supported in the browser");
};

class _Timer implements Timer {
  static const int _STATE_TIMEOUT = 0;
  static const int _STATE_INTERVAL = 1;
  int _state;

  _Timer(int milliSeconds, void callback(Timer timer), bool repeating) {
    if (repeating) {
      _state = (window._setInterval(() {
                callback(this);
              }, milliSeconds) <<
              1) |
          _STATE_INTERVAL;
    } else {
      _state = (window._setTimeout(() {
                _state = null;
                callback(this);
              }, milliSeconds) <<
              1) |
          _STATE_TIMEOUT;
    }
  }

  void cancel() {
    if (_state == null) return;
    int id = _state >> 1;
    if ((_state & 1) == _STATE_TIMEOUT) {
      window._clearTimeout(id);
    } else {
      window._clearInterval(id);
    }
    _state = null;
  }

  bool get isActive => _state != null;
}

get _timerFactoryClosure =>
    (int milliSeconds, void callback(Timer timer), bool repeating) {
      return new _Timer(milliSeconds, callback, repeating);
    };

class _PureIsolateTimer implements Timer {
  bool _isActive = true;
  final ReceivePort _port = new ReceivePort();
  SendPort _sendPort; // Effectively final.

  //  static SendPort _SEND_PORT;

  _PureIsolateTimer(int milliSeconds, callback, repeating) {
    _sendPort = _port.sendPort;
    _port.listen((msg) {
      assert(msg == _TIMER_PING);
      _isActive = repeating;
      callback(this);
      if (!repeating) _cancel();
    });

    _send([_NEW_TIMER, milliSeconds, repeating]);
  }

  void cancel() {
    _cancel();
    _send([_CANCEL_TIMER]);
  }

  void _cancel() {
    _isActive = false;
    _port.close();
  }

  _send(msg) {
    _sendToHelperIsolate(msg, _sendPort);
  }

  bool get isActive => _isActive;
}

get _pureIsolateTimerFactoryClosure =>
    ((int milliSeconds, void callback(Timer time), bool repeating) =>
        new _PureIsolateTimer(milliSeconds, callback, repeating));

class _ScheduleImmediateHelper {
  MutationObserver _observer;
  final DivElement _div = new DivElement();
  Function _callback;

  _ScheduleImmediateHelper() {
    // Run in the root-zone as the DOM callback would otherwise execute in the
    // current zone.
    Zone.root.run(() {
      // Mutation events get fired as soon as the current event stack is unwound
      // so we just make a dummy event and listen for that.
      _observer = new MutationObserver(_handleMutation);
      _observer.observe(_div, attributes: true);
    });
  }

  void _schedule(callback) {
    if (_callback != null) {
      throw new StateError(
          'Only one immediate callback can be scheduled at once');
    }
    _callback = callback;
    // Toggle it to trigger the mutation event.
    _div.hidden = !_div.hidden;
  }

  _handleMutation(List<MutationRecord> mutations, MutationObserver observer) {
    var tmp = _callback;
    _callback = null;
    tmp();
  }
}

final _ScheduleImmediateHelper _scheduleImmediateHelper =
    new _ScheduleImmediateHelper();

get _scheduleImmediateClosure => (void callback()) {
      _scheduleImmediateHelper._schedule(callback);
    };

get _pureIsolateScheduleImmediateClosure => ((void callback()) =>
    throw new UnimplementedError("scheduleMicrotask in background isolates "
        "are not supported in the browser"));

// Class for unsupported native browser 'DOM' objects.
class _UnsupportedBrowserObject extends DartHtmlDomObject {}
