// 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.

/**
 * Support for interoperating with JavaScript.
 *
 * This library provides access to JavaScript objects from Dart, allowing
 * Dart code to get and set properties, and call methods of JavaScript objects
 * and invoke JavaScript functions. The library takes care of converting
 * between Dart and JavaScript objects where possible, or providing proxies if
 * conversion isn't possible.
 *
 * This library does not yet make Dart objects usable from JavaScript, their
 * methods and proeprties are not accessible, though it does allow Dart
 * functions to be passed into and called from JavaScript.
 *
 * [JsObject] is the core type and represents a proxy of a JavaScript object.
 * JsObject gives access to the underlying JavaScript objects properties and
 * methods. `JsObject`s can be acquired by calls to JavaScript, or they can be
 * created from proxies to JavaScript constructors.
 *
 * The top-level getter [context] provides a [JsObject] that represents the
 * global object in JavaScript, usually `window`.
 *
 * The following example shows an alert dialog via a JavaScript call to the
 * global function `alert()`:
 *
 *     import 'dart:js';
 *
 *     main() => context.callMethod('alert', ['Hello from Dart!']);
 *
 * This example shows how to create a [JsObject] from a JavaScript constructor
 * and access its properties:
 *
 *     import 'dart:js';
 *
 *     main() {
 *       var object = new JsObject(context['Object']);
 *       object['greeting'] = 'Hello';
 *       object['greet'] = (name) => "${object['greeting']} $name";
 *       var message = object.callMethod('greet', ['JavaScript']);
 *       context['console'].callMethod('log', [message]);
 *     }
 *
 * ## Proxying and automatic conversion
 *
 * When setting properties on a JsObject or passing arguments to a Javascript
 * method or function, Dart objects are automatically converted or proxied to
 * JavaScript objects. When accessing JavaScript properties, or when a Dart
 * closure is invoked from JavaScript, the JavaScript objects are also
 * converted to Dart.
 *
 * Functions and closures are proxied in such a way that they are callable. A
 * Dart closure assigned to a JavaScript property is proxied by a function in
 * JavaScript. A JavaScript function accessed from Dart is proxied by a
 * [JsFunction], which has a [apply] method to invoke it.
 *
 * The following types are transferred directly and not proxied:
 *
 * * "Basic" types: `null`, `bool`, `num`, `String`, `DateTime`
 * * `Blob`
 * * `Event`
 * * `HtmlCollection`
 * * `ImageData`
 * * `KeyRange`
 * * `Node`
 * * `NodeList`
 * * `TypedData`, including its subclasses like `Int32List`, but _not_
 *   `ByteBuffer`
 * * `Window`
 *
 * ## Converting collections with JsObject.jsify()
 *
 * To create a JavaScript collection from a Dart collection use the
 * [JsObject.jsify] constructor, which converts Dart [Map]s and [Iterable]s
 * into JavaScript Objects and Arrays.
 *
 * The following expression creats a new JavaScript object with the properties
 * `a` and `b` defined:
 *
 *     var jsMap = new JsObject.jsify({'a': 1, 'b': 2});
 *
 * This expression creates a JavaScript array:
 *
 *     var jsArray = new JsObject.jsify([1, 2, 3]);
 */
library dart.js;

import 'dart:collection' show ListMixin;
import 'dart:nativewrappers';
import 'dart:math' as math;
import 'dart:mirrors' as mirrors;
import 'dart:html' as html;
import 'dart:indexed_db' as indexed_db;
import 'dart:typed_data';

// Pretend we are always in checked mode as we aren't interested in users
// running Dartium code outside of checked mode.
final bool CHECK_JS_INVOCATIONS = true;

final _allowedMethods = new Map<Symbol, _DeclarationSet>();
final _allowedGetters = new Map<Symbol, _DeclarationSet>();
final _allowedSetters = new Map<Symbol, _DeclarationSet>();

final _jsInterfaceTypes = new Set<Type>();
Iterable<Type> get jsInterfaceTypes => _jsInterfaceTypes;

/// A collection of methods where all methods have the same name.
/// This class is intended to optimize whether a specific invocation is
/// appropritate for at least some of the methods in the collection.
class _DeclarationSet {
  _DeclarationSet() : _members = <mirrors.DeclarationMirror>[];

  static bool _checkType(obj, mirrors.TypeMirror type) {
    if (obj == null) return true;
    return mirrors.reflectType(obj.runtimeType).isSubtypeOf(type);
  }

  /// Returns whether the return [value] has a type is consistent with the
  /// return type from at least one of the members matching the DeclarationSet.
  bool _checkReturnType(value) {
    if (value == null) return true;
    var valueMirror = mirrors.reflectType(value.runtimeType);
    for (var member in _members) {
      if (member is mirrors.VariableMirror || member.isGetter) {
        // TODO(jacobr): actually check return types for getters that return
        // function types.
        return true;
      } else {
        if (valueMirror.isSubtypeOf(member.returnType)) return true;
      }
    }
    return false;
  }

  /**
   * Check whether the [invocation] is consistent with the [member] mirror.
   */
  bool _checkDeclaration(
      Invocation invocation, mirrors.DeclarationMirror member) {
    if (member is mirrors.VariableMirror || (member as dynamic).isGetter) {
      // TODO(jacobr): actually check method types against the function type
      // returned by the getter or field.
      return true;
    }
    var parameters = (member as dynamic).parameters;
    var positionalArguments = invocation.positionalArguments;
    // Too many arguments
    if (parameters.length < positionalArguments.length) return false;
    // Too few required arguments.
    if (parameters.length > positionalArguments.length &&
        !parameters[positionalArguments.length].isOptional) return false;
    for (var i = 0; i < positionalArguments.length; i++) {
      if (parameters[i].isNamed) {
        // Not enough positional arguments.
        return false;
      }
      if (!_checkType(
          invocation.positionalArguments[i], parameters[i].type)) return false;
    }
    if (invocation.namedArguments.isNotEmpty) {
      var startNamed;
      for (startNamed = parameters.length - 1; startNamed >= 0; startNamed--) {
        if (!parameters[startNamed].isNamed) break;
      }
      startNamed++;

      // TODO(jacobr): we are unneccessarily using an O(n^2) algorithm here.
      // If we have JS APIs with a lange number of named parameters we should
      // optimize this. Either use a HashSet or invert this, walking over
      // parameters, querying invocation, and making sure we match
      //invocation.namedArguments.size keys.
      for (var name in invocation.namedArguments.keys) {
        bool match = false;
        for (var j = startNamed; j < parameters.length; j++) {
          var p = parameters[j];
          if (p.simpleName == name) {
            if (!_checkType(invocation.namedArguments[name],
                parameters[j].type)) return false;
            match = true;
            break;
          }
        }
        if (match == false) return false;
      }
    }
    return true;
  }

  bool checkInvocation(Invocation invocation) {
    for (var member in _members) {
      if (_checkDeclaration(invocation, member)) return true;
    }
    return false;
  }

  void add(mirrors.DeclarationMirror mirror) {
    _members.add(mirror);
  }

  final List<mirrors.DeclarationMirror> _members;
}

/**
 * Temporary method that we hope to remove at some point. This method should
 * generally only be called by machine generated code.
 */

void registerJsInterfaces([List<Type> classes]) {
  // This method is now obsolete in Dartium.
}

void _registerJsInterfaces(List<Type> classes) {
  for (Type type in classes) {
    if (!_jsInterfaceTypes.add(type)) continue; // Already registered.
    mirrors.ClassMirror typeMirror = mirrors.reflectType(type);
    typeMirror.declarations.forEach((symbol, declaration) {
      if (declaration is mirrors.MethodMirror ||
          declaration is mirrors.VariableMirror && !declaration.isStatic) {
        bool treatAsGetter = false;
        bool treatAsSetter = false;
        if (declaration is mirrors.VariableMirror) {
          treatAsGetter = true;
          if (!declaration.isConst && !declaration.isFinal) {
            treatAsSetter = true;
          }
        } else {
          if (declaration.isGetter) {
            treatAsGetter = true;
          } else if (declaration.isSetter) {
            treatAsSetter = true;
          } else if (!declaration.isConstructor) {
            _allowedMethods
                .putIfAbsent(symbol, () => new _DeclarationSet())
                .add(declaration);
          }
        }
        if (treatAsGetter) {
          _allowedGetters
              .putIfAbsent(symbol, () => new _DeclarationSet())
              .add(declaration);
          _allowedMethods
              .putIfAbsent(symbol, () => new _DeclarationSet())
              .add(declaration);
        }
        if (treatAsSetter) {
          _allowedSetters
              .putIfAbsent(symbol, () => new _DeclarationSet())
              .add(declaration);
        }
      }
    });
  }
}

_finalizeJsInterfaces() native "Js_finalizeJsInterfaces";

String _getJsName(mirrors.DeclarationMirror mirror) {
  for (var annotation in mirror.metadata) {
    if (mirrors.MirrorSystem.getName(annotation.type.simpleName) == "Js") {
      mirrors.LibraryMirror library = annotation.type.owner;
      var uri = library.uri;
      // make sure the annotation is from package://js
      if (uri.scheme == 'package' && uri.path == 'js/js.dart') {
        try {
          var name = annotation.reflectee.name;
          return name != null ? name : "";
        } catch (e) {
        }
      }
    }
  }
  return null;
}

bool _hasJsName(mirrors.DeclarationMirror mirror) =>
  _getJsName(mirror) != null;


_getJsMemberName(mirrors.DeclarationMirror mirror) {
  var name = _getJsName(mirror);
  return name == null || name.isEmpty ? _getDeclarationName(mirror) :
      name;
}

// TODO(jacobr): handle setters correctyl.
String _getDeclarationName(mirrors.DeclarationMirror declaration) {
  var name = mirrors.MirrorSystem.getName(declaration.simpleName);
  if (declaration is mirrors.MethodMirror && declaration.isSetter) {
    assert(name.endsWith("="));
    name = name.substring(0, name.length - 1);
  }
  return name;
}

final _JS_LIBRARY_PREFIX = "js_library";
final _UNDEFINED_VAR = "_UNDEFINED_JS_CONST";

String _accessJsPath(String path) =>
    "${_JS_LIBRARY_PREFIX}.context${path.split(".").map((p) => "['$p']").join('')}";

void addMemberHelper(mirrors.MethodMirror declaration, String path, StringBuffer sb, {bool isStatic: false, String memberName}) {
  var jsName = _getJsMemberName(declaration);
  path = (path != null && path.isNotEmpty) ? "${path}.${jsName}" : jsName;
  var name = memberName != null ? memberName : _getDeclarationName(declaration);
  if (declaration.isConstructor) {
    sb.write("factory");
  } else if (isStatic) {
    sb.write("static");
  } else {
    sb.write("patch");
  }
  sb.write(" ");
  if (declaration.isGetter) {
    sb.write("get $name => ${_accessJsPath(path)};");
  } else if (declaration.isSetter) {
    sb.write("set $name(v) => ${_accessJsPath(path)} = v;");
  } else {
    sb.write("$name(");
    bool hasOptional = false;
    int i = 0;
    var args = <String>[];
    for (var p in declaration.parameters) {
      assert(!p.isNamed); // XXX throw
      assert(!p.hasDefaultValue);
      if (i > 0) {
        sb.write(", ");
      }
      if (p.isOptional && !hasOptional) {
        sb.write("[");
        hasOptional = true;
      }
      var arg = "p$i";
      args.add(arg);
      sb.write(arg);
      if (p.isOptional) {
        sb.write("=${_UNDEFINED_VAR}");
      }
      i++;
    }
    if (hasOptional) {
      sb.write("]");
    }
    // TODO(jacobr):
    sb.write(") => ");
    if (declaration.isConstructor) {
        sb.write("new ${_JS_LIBRARY_PREFIX}.JsObject(");
    }
    sb
      ..write(_accessJsPath(path))
      ..write(declaration.isConstructor ? "," : ".apply(")
      ..write("[${args.join(",")}]");

    if (hasOptional) {
      sb.write(".takeWhile((i) => i != ${_UNDEFINED_VAR}).toList()");
    }
    sb.write(");");
  }
  sb.write("\n");
}

// TODO(jacobr): make this check more robust.
bool _isExternal(mirrors.MethodMirror mirror) =>
    mirror.source != null && mirror.source.startsWith("external ");

List<String> _generateExternalMethods() {
  var staticCodegen = <String>[];
  mirrors.currentMirrorSystem().libraries.forEach((uri, library) {
    var sb = new StringBuffer();
    String jsLibraryName = _getJsName(library);
    library.declarations.forEach((name, declaration) {
      if (declaration is mirrors.MethodMirror) {
        if (_isExternal(declaration) && (_hasJsName(declaration) || jsLibraryName != null)) {
          addMemberHelper(declaration, jsLibraryName, sb);
        }
      } else if (declaration is mirrors.ClassMirror) {
        mirrors.ClassMirror clazz = declaration;
        if (_hasJsName(clazz)) {
          // TODO(jacobr): verify class implements JavaScriptObject.
          assert(clazz.hasReflectedType);
          jsInterfaceTypes.add(clazz.reflectedType);
          String jsClassName = _getJsMemberName(clazz);
          var className = mirrors.MirrorSystem.getName(clazz.simpleName);
          var sbPatch = new StringBuffer();
          clazz.declarations.forEach((name, declaration) {
            if (declaration is! mirrors.MethodMirror || !_isExternal(declaration)) return;
            if (declaration.isFactoryConstructor) {
              sbPatch.write("  factory ${className}({");
              int i = 0;
              var args = <String>[];
              for (var p in declaration.parameters) {
                assert(p.isNamed); // XXX throw
                args.add(mirrors.MirrorSystem.getName(p.simpleName));
                i++;
              }
              sbPatch
                ..write(args.map((name) => '$name:${_UNDEFINED_VAR}').join(", "))
                ..write("}) {\n"
                        "    var ret = new ${_JS_LIBRARY_PREFIX}.JsObject.jsify({});\n");
              i = 0;
              for (var p in declaration.parameters) {
                assert(p.isNamed); // XXX throw
                var name = args[i];
                var jsName = mirrors.MirrorSystem.getName(p.simpleName);
                // XXX apply name conversion rules.
                sbPatch.write("    if($name != ${_UNDEFINED_VAR}) ret['$jsName'] = $name;\n");
                i++;
              }

              sbPatch.write("    return ret;\n"
                            "  }\n");
            } else if (declaration.isConstructor) {
              sbPatch.write("  ");
              addMemberHelper(declaration,
                  (jsLibraryName != null && jsLibraryName.isNotEmpty) ? "${jsLibraryName}" : "",
                  sbPatch,
                  isStatic: true,
                  memberName: className);
            }
          });

          clazz.staticMembers.forEach((memberName, member) {
            if (_isExternal(member)) {
              sbPatch.write("  ");
              addMemberHelper(member,
                  (jsLibraryName != null && jsLibraryName.isNotEmpty) ? "${jsLibraryName}.${jsClassName}" : jsClassName,
                  sbPatch,
                  isStatic: true);
            }
          });
          if (sbPatch.isNotEmpty) {
            sb.write("""
patch class $className {
$sbPatch
}
""");
          }
        }
      }
    });
    if (sb.isNotEmpty) {
      staticCodegen
        ..add(uri.toString())
        ..add("${uri}_js_interop_patch.dart")
        ..add("""
import 'dart:js' as ${_JS_LIBRARY_PREFIX};

/**
 * Placeholder object for cases where we need to determine exactly how many
 * args were passed to a function.
 */
const ${_UNDEFINED_VAR} = const Object();

${sb}
""");
    }
  });

  return staticCodegen;
}

/**
 * Generates a part file defining source code for JsObjectImpl and related
 * classes. This calass is needed so that type checks for all registered JavaScript
 * interop classes pass.
 */
List<String> _generateInteropPatchFiles() {
  var ret = _generateExternalMethods();
  var libraryPrefixes = new Map<mirrors.LibraryMirror, String>();
  var prefixNames = new Set<String>();
  var sb = new StringBuffer();

  var implements = <String>[];
  var implementsArray = <String>[];
  var listMirror = mirrors.reflectType(List);

  for (var type in jsInterfaceTypes) {
    mirrors.ClassMirror typeMirror = mirrors.reflectType(type);
    mirrors.LibraryMirror libraryMirror = typeMirror.owner;
    var prefixName;
    if (libraryPrefixes.containsKey(libraryMirror)) {
      prefixName = libraryPrefixes[libraryMirror];
    } else {
      var basePrefixName =
          mirrors.MirrorSystem.getName(libraryMirror.simpleName);
      basePrefixName = basePrefixName.replaceAll('.', '_');
      if (basePrefixName.isEmpty) basePrefixName = "lib";
      prefixName = basePrefixName;
      var i = 1;
      while (prefixNames.contains(prefixName)) {
        prefixName = '$basePrefixName$i';
        i++;
      }
      prefixNames.add(prefixName);
      libraryPrefixes[libraryMirror] = prefixName;
    }
    var isArray = typeMirror.isSubtypeOf(listMirror);
    (isArray ? implementsArray : implements).add(
        '${prefixName}.${mirrors.MirrorSystem.getName(typeMirror.simpleName)}');
  }
  libraryPrefixes.forEach((libraryMirror, prefix) {
    sb.writeln('import "${libraryMirror.uri}" as $prefix;');
  });
  buildImplementsClause(classes) =>
      classes.isEmpty ? "" : "implements ${classes.join(', ')}"
  var implementsClause = buildImplementsClause(implements);
  // TODO(jacobr): only certain classes need to be implemented by
  // JsFunctionImpl.
  var allTypes = []..addAll(implements)..addAll(implementsArray);
  sb.write('''
class JsObjectImpl extends JsObject $implementsClause {
  JsObjectImpl.internal() : super.internal();
}

class JsFunctionImpl extends JsFunction $implementsClause {
  JsFunctionImpl.internal() : super.internal();
}

class JsArrayImpl<E> extends JsArray<E> ${buildImplementsClause(implementsArray)} {
  JsArrayImpl.internal() : super.internal();
}

_registerAllJsInterfaces() {
  _registerJsInterfaces([${allTypes.join(", ")}]);
}

''');
  ret..addAll(["dart:js", "JsInteropImpl.dart", sb.toString()]);
  return ret;
}

// Start of block of helper methods facilitating emulating JavaScript Array
// methods on Dart List objects passed to JavaScript via JS interop.
// TODO(jacobr): match JS more closely.
String _toStringJs(obj) => '$obj';

// TODO(jacobr): this might not exactly match JS semantics but should be
// adequate for now.
int _toIntJs(obj) {
  if (obj is int) return obj;
  if (obj is num) return obj.toInt();
  return num.parse('$obj'.trim(), (_) => 0).toInt();
}

// TODO(jacobr): this might not exactly match JS semantics but should be
// adequate for now.
num _toNumJs(obj) {
  return obj is num ? obj : num.parse('$obj'.trim(), (_) => 0);
}

/// Match the behavior of setting List length in JavaScript with the exception
/// that Dart does not distinguish undefined and null.
_setListLength(List list, rawlen) {
  num len = _toNumJs(rawlen);
  if (len is! int || len < 0) {
    throw new RangeError("Invalid array length");
  }
  if (len > list.length) {
    _arrayExtend(list, len);
  } else if (len < list.length) {
    list.removeRange(len, list.length);
  }
  return rawlen;
}

// TODO(jacobr): should we really bother with this method instead of just
// shallow copying to a JS array and calling the JavaScript join method?
String _arrayJoin(List list, sep) {
  if (sep == null) {
    sep = ",";
  }
  return list.map((e) => e == null ? "" : e.toString()).join(sep.toString());
}

// TODO(jacobr): should we really bother with this method instead of just
// shallow copying to a JS array and using the toString method?
String _arrayToString(List list) => _arrayJoin(list, ",");

int _arrayPush(List list, List args) {
  for(var e in args) {
    list.add(e);
  }
  return list.length;
}

_arrayPop(List list) {
  if (list.length > 0) return list.removeLast();
}

// TODO(jacobr): would it be better to just copy input to a JS List
// and call Array.concat?
List _arrayConcat(List input, List args) {
  var ret = new List.from(input);
  for (var e in args) {
    // TODO(jacobr): technically in ES6 we should use
    // Symbol.isConcatSpreadable to determine whether call addAll. Once v8
    // supports it, we can make all Dart classes implementing Iterable
    // specify isConcatSpreadable and tweak this behavior to allow Iterable.
    if (e is List) {
      ret.addAll(e);
    } else {
      ret.add(e);
    }
  }
  return ret;
}

List _arraySplice(List input, List args) {
  int start = 0;
  if (args.length > 0) {
    var rawStart = _toIntJs(args[0]);
    if (rawStart < 0) {
      start = math.max(0, input.length - rawStart);
    } else {
      start = math.min(input.length, rawStart);
    }
  }
  var end = start;
  if (args.length > 1) {
    var rawDeleteCount = _toIntJs(args[1]);
    if (rawDeleteCount < 0) rawDeleteCount = 0;
    end = math.min(input.length, start + rawDeleteCount);
  }
  var replacement = [];
  var removedElements = input.getRange(start, end).toList();
  if (args.length > 2) {
    replacement = args.getRange(2, args.length);
  }
  input.replaceRange(start, end, replacement);
  return removedElements;
}

List _arrayReverse(List l) {
  for (var i = 0, j = l.length - 1; i < j; i++, j--) {
    var tmp = l[i];
    l[i] = l[j];
    l[j] = tmp;
  }
  return l;
}

_arrayShift(List l) {
  if (l.isEmpty) return null; // Technically we should return undefined.
  return l.removeAt(0);
}

int _arrayUnshift(List l, List args) {
  l.insertAll(0, args);
  return l.length;
}

_arrayExtend(List l, int newLength) {
  for (var i = l.length; i < newLength; i++) {
    // TODO(jacobr): we'd really like to add undefined to better match
    // JavaScript semantics.
    l.add(null);
  }
}

List _arraySort(List l, rawCompare) {
  // TODO(jacobr): alternately we could just copy the Array to JavaScript,
  // invoke the JS sort method and then copy the result back to Dart.
  Comparator compare;
  if (rawCompare == null) {
    compare = (a, b) => _toStringJs(a).compareTo(_toStringJs(b));
  } else if (rawCompare is JsFunction) {
    compare = (a, b) => rawCompare.apply([a, b]);
  } else {
    compare = rawCompare;
  }
  l.sort(compare);
  return l;
}
// End of block of helper methods to emulate JavaScript Array methods on Dart List.

/**
 * Can be called to provide a predictable point where no more JS interfaces can
 * be added. Creating an instance of JsObject will also automatically trigger
 * all JsObjects to be finalized.
 */
void finalizeJsInterfaces() {
  if (_finalized == true) {
    throw 'JSInterop class registration already finalized';
  }
  _finalizeJsInterfaces();
}

JsObject _cachedContext;

JsObject get _context native "Js_context_Callback";

bool get _finalized native "Js_interfacesFinalized_Callback";

JsObject get context {
  if (_cachedContext == null) {
    _cachedContext = _context;
  }
  return _cachedContext;
}

_maybeWrap(o) {
  var wrapped = html.wrap_jso_no_SerializedScriptvalue(o);
  if (identical(wrapped, o)) return o;
  return (wrapped is html.Blob
      || wrapped is html.Event
      || wrapped is indexed_db.KeyRange
      || wrapped is html.ImageData
      || wrapped is html.Node
      || wrapped is TypedData
      || wrapped is html.Window) ? wrapped : o;
}

/**
 * Get the dart wrapper object for object. Top-level so we
 * we can access it from other libraries without it being
 * a public instance field on JsObject.
 */
getDartHtmlWrapperFor(JsObject object) => object._dartHtmlWrapper;

/**
 * Set the dart wrapper object for object. Top-level so we
 * we can access it from other libraries without it being
 * a public instance field on JsObject.
 */
void setDartHtmlWrapperFor(JsObject object, wrapper) {
  object._dartHtmlWrapper = wrapper;
}

/**
 * Used by callMethod to get the JS object for each argument passed if the
 * argument is a Dart class instance that delegates to a DOM object.  See
 * wrap_jso defined in dart:html.
 */
unwrap_jso(dartClass_instance) {
  if (dartClass_instance is html.DartHtmlDomObject)
    return dartClass_instance.blink_jsObject;
  else
    return dartClass_instance;
}

/**
 * Proxies a JavaScript object to Dart.
 *
 * The properties of the JavaScript object are accessible via the `[]` and
 * `[]=` operators. Methods are callable via [callMethod].
 */
class JsObject extends NativeFieldWrapperClass2 {
  JsObject.internal();

  /**
   * If this JsObject is wrapped, e.g. DOM objects, then we can save the
   * wrapper here and preserve its identity.
   */
  var _dartHtmlWrapper;

  /**
   * Constructs a new JavaScript object from [constructor] and returns a proxy
   * to it.
   */
  factory JsObject(JsFunction constructor, [List arguments]) {
    try {
      return _create(constructor, arguments);
    } catch (e) {
      // Re-throw any errors (returned as a string) as a DomException.
      throw new html.DomException.jsInterop(e);
    }
  }

  static JsObject _create(
      JsFunction constructor, arguments) native "JsObject_constructorCallback";

  _buildArgs(Invocation invocation) {
    if (invocation.namedArguments.isEmpty) {
      return invocation.positionalArguments;
    } else {
      var varArgs = new Map<String, Object>();
      invocation.namedArguments.forEach((symbol, val) {
        varArgs[mirrors.MirrorSystem.getName(symbol)] = val;
      });
      return invocation.positionalArguments.toList()
        ..add(new JsObject.jsify(varArgs));
    }
  }

  /**
   * Constructs a [JsObject] that proxies a native Dart object; _for expert use
   * only_.
   *
   * Use this constructor only if you wish to get access to JavaScript
   * properties attached to a browser host object, such as a Node or Blob, that
   * is normally automatically converted into a native Dart object.
   *
   * An exception will be thrown if [object] either is `null` or has the type
   * `bool`, `num`, or `String`.
   */
  factory JsObject.fromBrowserObject(object) {
    if (object is num || object is String || object is bool || object == null) {
      throw new ArgumentError("object cannot be a num, string, bool, or null");
    }
    return _fromBrowserObject(object);
  }

  /**
   * Recursively converts a JSON-like collection of Dart objects to a
   * collection of JavaScript objects and returns a [JsObject] proxy to it.
   *
   * [object] must be a [Map] or [Iterable], the contents of which are also
   * converted. Maps and Iterables are copied to a new JavaScript object.
   * Primitives and other transferrable values are directly converted to their
   * JavaScript type, and all other objects are proxied.
   */
  factory JsObject.jsify(object) {
    if ((object is! Map) && (object is! Iterable)) {
      throw new ArgumentError("object must be a Map or Iterable");
    }
    return _jsify(object);
  }

  static JsObject _jsify(object) native "JsObject_jsify";

  static JsObject _fromBrowserObject(object) => html.unwrap_jso(object);

  /**
   * Returns the value associated with [property] from the proxied JavaScript
   * object.
   *
   * The type of [property] must be either [String] or [num].
   */
  operator [](property) {
    try {
      return _maybeWrap(_operator_getter(property));
    } catch (e) {
      // Re-throw any errors (returned as a string) as a DomException.
      throw new html.DomException.jsInterop(e);
    }
  }
  _operator_getter(property) native "JsObject_[]";

  /**
   * Sets the value associated with [property] on the proxied JavaScript
   * object.
   *
   * The type of [property] must be either [String] or [num].
   */
  operator []=(property, value) {
    try {
      _operator_setter(property, value);
    } catch (e) {
      // Re-throw any errors (returned as a string) as a DomException.
      throw new html.DomException.jsInterop(e);
    }
  }
  _operator_setter(property, value) native "JsObject_[]=";

  int get hashCode native "JsObject_hashCode";

  operator ==(other) {
    var is_JsObject = other is JsObject;
    if (!is_JsObject) {
      other = html.unwrap_jso(other);
      is_JsObject = other is JsObject;
    }
    return is_JsObject && _identityEquality(this, other);
  }

  static bool _identityEquality(
      JsObject a, JsObject b) native "JsObject_identityEquality";

  /**
   * Returns `true` if the JavaScript object contains the specified property
   * either directly or though its prototype chain.
   *
   * This is the equivalent of the `in` operator in JavaScript.
   */
  bool hasProperty(String property) native "JsObject_hasProperty";

  /**
   * Removes [property] from the JavaScript object.
   *
   * This is the equivalent of the `delete` operator in JavaScript.
   */
  void deleteProperty(String property) native "JsObject_deleteProperty";

  /**
   * Returns `true` if the JavaScript object has [type] in its prototype chain.
   *
   * This is the equivalent of the `instanceof` operator in JavaScript.
   */
  bool instanceof(JsFunction type) native "JsObject_instanceof";

  /**
   * Returns the result of the JavaScript objects `toString` method.
   */
  String toString() {
    try {
      return _toString();
    } catch (e) {
      return super.toString();
    }
  }

  String _toString() native "JsObject_toString";

  /**
   * Calls [method] on the JavaScript object with the arguments [args] and
   * returns the result.
   *
   * The type of [method] must be either [String] or [num].
   */
  callMethod(String method, [List args]) {
    try {
      return _maybeWrap(_callMethod(method, args));
    } catch (e) {
      if (hasProperty(method)) {
        // Return a DomException if DOM call returned an error.
        throw new html.DomException.jsInterop(e);
      } else {
        throw new NoSuchMethodError(this, new Symbol(method), args, null);
      }
    }
  }

  noSuchMethod(Invocation invocation) {
    throwError() {
      throw new NoSuchMethodError(this, invocation.memberName,
          invocation.positionalArguments, invocation.namedArguments);
    }

    String name = mirrors.MirrorSystem.getName(invocation.memberName);
    if (invocation.isGetter) {
      if (CHECK_JS_INVOCATIONS) {
        var matches = _allowedGetters[invocation.memberName];
        if (matches == null &&
            !_allowedMethods.containsKey(invocation.memberName)) {
          throwError();
        }
        var ret = this[name];
        if (matches != null && matches._checkReturnType(ret)) return ret;
        if (ret is Function ||
            (ret is JsFunction /* shouldn't be needed in the future*/) &&
                _allowedMethods.containsKey(
                    invocation.memberName)) return ret; // Warning: we have not bound "this"... we could type check on the Function but that is of little value in Dart.
        throwError();
      } else {
        // TODO(jacobr): should we throw if the JavaScript object doesn't have the property?
        return this[name];
      }
    } else if (invocation.isSetter) {
      if (CHECK_JS_INVOCATIONS) {
        var matches = _allowedSetters[invocation.memberName];
        if (matches == null ||
            !matches.checkInvocation(invocation)) throwError();
      }
      assert(name.endsWith("="));
      name = name.substring(0, name.length - 1);
      return this[name] = invocation.positionalArguments.first;
    } else {
      // TODO(jacobr): also allow calling getters that look like functions.
      var matches;
      if (CHECK_JS_INVOCATIONS) {
        matches = _allowedMethods[invocation.memberName];
        if (matches == null ||
            !matches.checkInvocation(invocation)) throwError();
      }
      var ret = this.callMethod(name, _buildArgs(invocation));
      if (CHECK_JS_INVOCATIONS) {
        if (!matches._checkReturnType(ret)) throwError();
      }
      return ret;
    }
  }

  _callMethod(String name, List args) native "JsObject_callMethod";
}

// JavaScript interop methods that do not automatically wrap to dart:html types.
// Warning: this API is not exposed to dart:js.
class JsNative {
  static getProperty(JsObject o, name) {
    return o._operator_getter(name);
  }

  static callMethod(JsObject o, String method, List args) {
    return o._callMethod(method, args);
  }

  static getArrayIndex(JsArray array, int index) {
    array._checkIndex(index);
    return getProperty(array, index);
  }

  /**
   * Same behavior as new JsFunction.withThis except that JavaScript "this" is not
   * wrapped.
   */
  static JsFunction withThis(Function f) native "JsFunction_withThisNoWrap";
}

/**
 * Proxies a JavaScript Function object.
 */
class JsFunction extends JsObject implements Function {
  JsFunction.internal() : super.internal();

  /**
   * Returns a [JsFunction] that captures its 'this' binding and calls [f]
   * with the value of this passed as the first argument.
   */
  factory JsFunction.withThis(Function f) => _withThis(f);

  /**
   * Invokes the JavaScript function with arguments [args]. If [thisArg] is
   * supplied it is the value of `this` for the invocation.
   */
  dynamic apply(List args, {thisArg}) =>
    _maybeWrap(_apply(args, thisArg: thisArg));

  dynamic _apply(List args, {thisArg}) native "JsFunction_apply";

  noSuchMethod(Invocation invocation) {
    if (invocation.isMethod && invocation.memberName == #call) {
      return apply(_buildArgs(invocation));
    }
    return super.noSuchMethod(invocation);
  }

  /**
   * Internal only version of apply which uses debugger proxies of Dart objects
   * rather than opaque handles. This method is private because it cannot be
   * efficiently implemented in Dart2Js so should only be used by internal
   * tools.
   */
  _applyDebuggerOnly(List args,
      {thisArg}) native "JsFunction_applyDebuggerOnly";

  static JsFunction _withThis(Function f) native "JsFunction_withThis";
}

/**
 * A [List] proxying a JavaScript Array.
 */
class JsArray<E> extends JsObject with ListMixin<E> {
  JsArray.internal() : super.internal();

  factory JsArray() => _newJsArray();

  static JsArray _newJsArray() native "JsArray_newJsArray";

  factory JsArray.from(Iterable<E> other) =>
      _newJsArrayFromSafeList(new List.from(other));

  static JsArray _newJsArrayFromSafeList(
      List list) native "JsArray_newJsArrayFromSafeList";

  _checkIndex(int index, {bool insert: false}) {
    int length = insert ? this.length + 1 : this.length;
    if (index is int && (index < 0 || index >= length)) {
      throw new RangeError.range(index, 0, length);
    }
  }

  _checkRange(int start, int end) {
    int cachedLength = this.length;
    if (start < 0 || start > cachedLength) {
      throw new RangeError.range(start, 0, cachedLength);
    }
    if (end < start || end > cachedLength) {
      throw new RangeError.range(end, start, cachedLength);
    }
  }

  // Methods required by ListMixin

  E operator [](index) {
    if (index is int) {
      _checkIndex(index);
    }

    return super[index];
  }

  void operator []=(index, E value) {
    if (index is int) {
      _checkIndex(index);
    }
    super[index] = value;
  }

  int get length native "JsArray_length";

  set length(int length) {
    super['length'] = length;
  }

  // Methods overriden for better performance

  void add(E value) {
    callMethod('push', [value]);
  }

  void addAll(Iterable<E> iterable) {
    // TODO(jacobr): this can be optimized slightly.
    callMethod('push', new List.from(iterable));
  }

  void insert(int index, E element) {
    _checkIndex(index, insert: true);
    callMethod('splice', [index, 0, element]);
  }

  E removeAt(int index) {
    _checkIndex(index);
    return callMethod('splice', [index, 1])[0];
  }

  E removeLast() {
    if (length == 0) throw new RangeError(-1);
    return callMethod('pop');
  }

  void removeRange(int start, int end) {
    _checkRange(start, end);
    callMethod('splice', [start, end - start]);
  }

  void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
    _checkRange(start, end);
    int length = end - start;
    if (length == 0) return;
    if (skipCount < 0) throw new ArgumentError(skipCount);
    var args = [start, length]..addAll(iterable.skip(skipCount).take(length));
    callMethod('splice', args);
  }

  void sort([int compare(E a, E b)]) {
    callMethod('sort', [compare]);
  }
}

/**
 * Placeholder object for cases where we need to determine exactly how many
 * args were passed to a function.
 */
const _UNDEFINED = const Object();

// TODO(jacobr): this method is a hack to work around the lack of proper dart
// support for varargs methods.
List _stripUndefinedArgs(List args) =>
    args.takeWhile((i) => i != _UNDEFINED).toList();

/**
 * Returns a method that can be called with an arbitrary number (for n less
 * than 11) of arguments without violating Dart type checks.
 */
Function _wrapAsDebuggerVarArgsFunction(JsFunction jsFunction) =>
    ([a1 = _UNDEFINED, a2 = _UNDEFINED, a3 = _UNDEFINED, a4 = _UNDEFINED,
        a5 = _UNDEFINED, a6 = _UNDEFINED, a7 = _UNDEFINED, a8 = _UNDEFINED,
        a9 = _UNDEFINED, a10 = _UNDEFINED]) => jsFunction._applyDebuggerOnly(
            _stripUndefinedArgs([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10]));

// This method is a no-op in Dartium.
// TODO(jacobr): tag methods so we can throw if a Dart method is passed to
// JavaScript using the new interop without calling allowInterop.
Function allowInterop(Function f) => f;

Expando<JsFunction> _interopCaptureThisExpando = new Expando<JsFunction>();

Function allowInteropCaptureThis(Function f) {
  if (f is JsFunction) {
    // Behavior when the function is already a JS function is unspecified.
    throw new ArgumentError(
        "Function is already a JS function so cannot capture this.");
    return f;
  } else {
    var ret = _interopCaptureThisExpando[f];
    if (ret == null) {
      ret = new JsFunction.withThis(f);
      _interopCaptureThisExpando[f] = ret;
    }
    return ret;
  }
}
