| Index: sdk/lib/_internal/compiler/js_lib/js_rti.dart
 | 
| diff --git a/sdk/lib/_internal/compiler/js_lib/js_rti.dart b/sdk/lib/_internal/compiler/js_lib/js_rti.dart
 | 
| deleted file mode 100644
 | 
| index e5669e2a6babfca6dfcb3b2d8269714294549f74..0000000000000000000000000000000000000000
 | 
| --- a/sdk/lib/_internal/compiler/js_lib/js_rti.dart
 | 
| +++ /dev/null
 | 
| @@ -1,681 +0,0 @@
 | 
| -// 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.
 | 
| -
 | 
| -/**
 | 
| - * This part contains helpers for supporting runtime type information.
 | 
| - *
 | 
| - * The helper use a mixture of Dart and JavaScript objects. To indicate which is
 | 
| - * used where we adopt the scheme of using explicit type annotation for Dart
 | 
| - * objects and 'var' or omitted return type for JavaScript objects.
 | 
| - *
 | 
| - * Since bool, int, and String values are represented by the same JavaScript
 | 
| - * primitives, type annotations are used for these types in all cases.
 | 
| - *
 | 
| - * Several methods use a common JavaScript encoding of runtime type information.
 | 
| - * This encoding is referred to as the type representation which is one of
 | 
| - * these:
 | 
| - *  1) a JavaScript constructor for a class C: the represented type is the raw
 | 
| - *     type C.
 | 
| - *  2) a JavaScript array: the first entry is of type 1 and contains the
 | 
| - *     subtyping flags and the substitution of the type and the rest of the
 | 
| - *     array are the type arguments.
 | 
| - *  3) `null`: the dynamic type.
 | 
| - *  4) a JavaScript object representing the function type. For instance, it has
 | 
| - *     the form  {ret: rti, args: [rti], opt: [rti], named: {name: rti}} for a
 | 
| - *     function with a return type, regular, optional and named arguments.
 | 
| - *
 | 
| - * To check subtype relations between generic classes we use a JavaScript
 | 
| - * expression that describes the necessary substitution for type arguments.
 | 
| - * Such a substitution expresssion can be:
 | 
| - *  1) `null`, if no substituted check is necessary, because the
 | 
| - *     type variables are the same or there are no type variables in the class
 | 
| - *     that is checked for.
 | 
| - *  2) A list expression describing the type arguments to be used in the
 | 
| - *     subtype check, if the type arguments to be used in the check do not
 | 
| - *     depend on the type arguments of the object.
 | 
| - *  3) A function mapping the type variables of the object to be checked to
 | 
| - *     a list expression. The function may also return null, which is equivalent
 | 
| - *     to an array containing only null values.
 | 
| - */
 | 
| -
 | 
| -part of _js_helper;
 | 
| -
 | 
| -Type createRuntimeType(String name) => new TypeImpl(name);
 | 
| -
 | 
| -class TypeImpl implements Type {
 | 
| -  final String _typeName;
 | 
| -  String _unmangledName;
 | 
| -
 | 
| -  TypeImpl(this._typeName);
 | 
| -
 | 
| -  String toString() {
 | 
| -    if (_unmangledName != null) return _unmangledName;
 | 
| -    String unmangledName =
 | 
| -        unmangleAllIdentifiersIfPreservedAnyways(_typeName);
 | 
| -    return _unmangledName = unmangledName;
 | 
| -  }
 | 
| -
 | 
| -  // TODO(ahe): This is a poor hashCode as it collides with its name.
 | 
| -  int get hashCode => _typeName.hashCode;
 | 
| -
 | 
| -  bool operator ==(other) {
 | 
| -    return  (other is TypeImpl) && _typeName == other._typeName;
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Represents a type variable.
 | 
| - *
 | 
| - * This class holds the information needed when reflecting on generic classes
 | 
| - * and their members.
 | 
| - */
 | 
| -class TypeVariable {
 | 
| -  final Type owner;
 | 
| -  final String name;
 | 
| -  final int bound;
 | 
| -
 | 
| -  const TypeVariable(this.owner, this.name, this.bound);
 | 
| -}
 | 
| -
 | 
| -getMangledTypeName(TypeImpl type) => type._typeName;
 | 
| -
 | 
| -/**
 | 
| - * Sets the runtime type information on [target]. [rti] is a type
 | 
| - * representation of type 4 or 5, that is, either a JavaScript array or
 | 
| - * `null`.
 | 
| - */
 | 
| -Object setRuntimeTypeInfo(Object target, var rti) {
 | 
| -  assert(rti == null || isJsArray(rti));
 | 
| -  // We have to check for null because factories may return null.
 | 
| -  if (target != null) JS('var', r'#.$builtinTypeInfo = #', target, rti);
 | 
| -  return target;
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Returns the runtime type information of [target]. The returned value is a
 | 
| - * list of type representations for the type arguments.
 | 
| - */
 | 
| -getRuntimeTypeInfo(Object target) {
 | 
| -  if (target == null) return null;
 | 
| -  return JS('var', r'#.$builtinTypeInfo', target);
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Returns the type arguments of [target] as an instance of [substitutionName].
 | 
| - */
 | 
| -getRuntimeTypeArguments(target, substitutionName) {
 | 
| -  var substitution = getField(target,
 | 
| -      '${JS_GET_NAME(JsGetName.OPERATOR_AS_PREFIX)}$substitutionName');
 | 
| -  return substitute(substitution, getRuntimeTypeInfo(target));
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Returns the [index]th type argument of [target] as an instance of
 | 
| - * [substitutionName].
 | 
| - */
 | 
| -@NoThrows() @NoSideEffects() @NoInline()
 | 
| -getRuntimeTypeArgument(Object target, String substitutionName, int index) {
 | 
| -  var arguments = getRuntimeTypeArguments(target, substitutionName);
 | 
| -  return arguments == null ? null : getIndex(arguments, index);
 | 
| -}
 | 
| -
 | 
| -@NoThrows() @NoSideEffects() @NoInline()
 | 
| -getTypeArgumentByIndex(Object target, int index) {
 | 
| -  var rti = getRuntimeTypeInfo(target);
 | 
| -  return rti == null ? null : getIndex(rti, index);
 | 
| -}
 | 
| -
 | 
| -void copyTypeArguments(Object source, Object target) {
 | 
| -  JS('var', r'#.$builtinTypeInfo = #.$builtinTypeInfo', target, source);
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Retrieves the class name from type information stored on the constructor
 | 
| - * of [object].
 | 
| - */
 | 
| -String getClassName(var object) {
 | 
| -  return rawRtiToJsConstructorName(getRawRuntimeType(getInterceptor(object)));
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Creates the string representation for the type representation [rti]
 | 
| - * of type 4, the JavaScript array, where the first element represents the class
 | 
| - * and the remaining elements represent the type arguments.
 | 
| - */
 | 
| -String getRuntimeTypeAsString(var rti, {String onTypeVariable(int i)}) {
 | 
| -  assert(isJsArray(rti));
 | 
| -  String className = rawRtiToJsConstructorName(getIndex(rti, 0));
 | 
| -  return '$className${joinArguments(rti, 1, onTypeVariable: onTypeVariable)}';
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Returns a human-readable representation of the type representation [rti].
 | 
| - */
 | 
| -String runtimeTypeToString(var rti, {String onTypeVariable(int i)}) {
 | 
| -  if (rti == null) {
 | 
| -    return 'dynamic';
 | 
| -  } else if (isJsArray(rti)) {
 | 
| -    // A list representing a type with arguments.
 | 
| -    return getRuntimeTypeAsString(rti, onTypeVariable: onTypeVariable);
 | 
| -  } else if (isJsFunction(rti)) {
 | 
| -    // A reference to the constructor.
 | 
| -    return rawRtiToJsConstructorName(rti);
 | 
| -  } else if (rti is int) {
 | 
| -    if (onTypeVariable == null) {
 | 
| -      return rti.toString();
 | 
| -    } else {
 | 
| -      return onTypeVariable(rti);
 | 
| -    }
 | 
| -  } else {
 | 
| -    // TODO(ahe): Handle function types, and be sure to always return a string.
 | 
| -    return null;
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Creates a comma-separated string of human-readable representations of the
 | 
| - * type representations in the JavaScript array [types] starting at index
 | 
| - * [startIndex].
 | 
| - */
 | 
| -String joinArguments(var types, int startIndex,
 | 
| -                     {String onTypeVariable(int i)}) {
 | 
| -  if (types == null) return '';
 | 
| -  assert(isJsArray(types));
 | 
| -  bool firstArgument = true;
 | 
| -  bool allDynamic = true;
 | 
| -  StringBuffer buffer = new StringBuffer();
 | 
| -  for (int index = startIndex; index < getLength(types); index++) {
 | 
| -    if (firstArgument) {
 | 
| -      firstArgument = false;
 | 
| -    } else {
 | 
| -      buffer.write(', ');
 | 
| -    }
 | 
| -    var argument = getIndex(types, index);
 | 
| -    if (argument != null) {
 | 
| -      allDynamic = false;
 | 
| -    }
 | 
| -    buffer.write(runtimeTypeToString(argument, onTypeVariable: onTypeVariable));
 | 
| -  }
 | 
| -  return allDynamic ? '' : '<$buffer>';
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Returns a human-readable representation of the type of [object].
 | 
| - *
 | 
| - * In minified mode does *not* use unminified identifiers (even when present).
 | 
| - */
 | 
| -String getRuntimeTypeString(var object) {
 | 
| -  String className = getClassName(object);
 | 
| -  if (object == null) return className;
 | 
| -  var rti = JS('var', r'#.$builtinTypeInfo', object);
 | 
| -  return "$className${joinArguments(rti, 0)}";
 | 
| -}
 | 
| -
 | 
| -Type getRuntimeType(var object) {
 | 
| -  String type = getRuntimeTypeString(object);
 | 
| -  return new TypeImpl(type);
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Applies the [substitution] on the [arguments].
 | 
| - *
 | 
| - * See the comment in the beginning of this file for a description of the
 | 
| - * possible values for [substitution].
 | 
| - */
 | 
| -substitute(var substitution, var arguments) {
 | 
| -  assert(substitution == null ||
 | 
| -         isJsFunction(substitution));
 | 
| -  assert(arguments == null || isJsArray(arguments));
 | 
| -  if (isJsFunction(substitution)) {
 | 
| -    substitution = invoke(substitution, arguments);
 | 
| -    if (substitution == null || isJsArray(substitution)) {
 | 
| -      arguments = substitution;
 | 
| -    } else if (isJsFunction(substitution)) {
 | 
| -      // TODO(johnniwinther): Check if this is still needed.
 | 
| -      arguments = invoke(substitution, arguments);
 | 
| -    }
 | 
| -  }
 | 
| -  return arguments;
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Perform a type check with arguments on the Dart object [object].
 | 
| - *
 | 
| - * Parameters:
 | 
| - * - [isField]: the name of the flag/function to check if the object
 | 
| - *   is of the correct class.
 | 
| - * - [checks]: the (JavaScript) list of type representations for the
 | 
| - *   arguments to check against.
 | 
| - * - [asField]: the name of the function that transforms the type
 | 
| - *   arguments of [objects] to an instance of the class that we check
 | 
| - *   against.
 | 
| - */
 | 
| -bool checkSubtype(Object object, String isField, List checks, String asField) {
 | 
| -  if (object == null) return false;
 | 
| -  var arguments = getRuntimeTypeInfo(object);
 | 
| -  // Interceptor is needed for JSArray and native classes.
 | 
| -  // TODO(sra): It could be a more specialized interceptor since [object] is not
 | 
| -  // `null` or a primitive.
 | 
| -  // TODO(9586): Move type info for static functions onto an interceptor.
 | 
| -  var interceptor = getInterceptor(object);
 | 
| -  var isSubclass = getField(interceptor, isField);
 | 
| -  // When we read the field and it is not there, [isSubclass] will be `null`.
 | 
| -  if (isSubclass == null) return false;
 | 
| -  // Should the asField function be passed the receiver?
 | 
| -  var substitution = getField(interceptor, asField);
 | 
| -  return checkArguments(substitution, arguments, checks);
 | 
| -}
 | 
| -
 | 
| -/// Returns the field's type name.
 | 
| -///
 | 
| -/// In minified mode, uses the unminified names if available.
 | 
| -String computeTypeName(String isField, List arguments) {
 | 
| -  // Extract the class name from the is field and append the textual
 | 
| -  // representation of the type arguments.
 | 
| -  return Primitives.formatType(isCheckPropertyToJsConstructorName(isField),
 | 
| -                               arguments);
 | 
| -}
 | 
| -
 | 
| -Object subtypeCast(Object object, String isField, List checks, String asField) {
 | 
| -  if (object != null && !checkSubtype(object, isField, checks, asField)) {
 | 
| -    String actualType = Primitives.objectTypeName(object);
 | 
| -    String typeName = computeTypeName(isField, checks);
 | 
| -    // TODO(johnniwinther): Move type lookup to [CastErrorImplementation] to
 | 
| -    // align with [TypeErrorImplementation].
 | 
| -    throw new CastErrorImplementation(actualType, typeName);
 | 
| -  }
 | 
| -  return object;
 | 
| -}
 | 
| -
 | 
| -Object assertSubtype(Object object, String isField, List checks,
 | 
| -                     String asField) {
 | 
| -  if (object != null && !checkSubtype(object, isField, checks, asField)) {
 | 
| -    String typeName = computeTypeName(isField, checks);
 | 
| -    throw new TypeErrorImplementation(object, typeName);
 | 
| -  }
 | 
| -  return object;
 | 
| -}
 | 
| -
 | 
| -/// Checks that the type represented by [subtype] is a subtype of [supertype].
 | 
| -/// If not a type error with [message] is thrown.
 | 
| -assertIsSubtype(var subtype, var supertype, String message) {
 | 
| -  if (!isSubtype(subtype, supertype)) {
 | 
| -    throwTypeError(message);
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -throwTypeError(message) {
 | 
| -  throw new TypeErrorImplementation.fromMessage(message);
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Check that the types in the list [arguments] are subtypes of the types in
 | 
| - * list [checks] (at the respective positions), possibly applying [substitution]
 | 
| - * to the arguments before the check.
 | 
| - *
 | 
| - * See the comment in the beginning of this file for a description of the
 | 
| - * possible values for [substitution].
 | 
| - */
 | 
| -bool checkArguments(var substitution, var arguments, var checks) {
 | 
| -  return areSubtypes(substitute(substitution, arguments), checks);
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Checks whether the types of [s] are all subtypes of the types of [t].
 | 
| - *
 | 
| - * [s] and [t] are either `null` or JavaScript arrays of type representations,
 | 
| - * A `null` argument is interpreted as the arguments of a raw type, that is a
 | 
| - * list of `dynamic`. If [s] and [t] are JavaScript arrays they must be of the
 | 
| - * same length.
 | 
| - *
 | 
| - * See the comment in the beginning of this file for a description of type
 | 
| - * representations.
 | 
| - */
 | 
| -bool areSubtypes(var s, var t) {
 | 
| -  // `null` means a raw type.
 | 
| -  if (s == null || t == null) return true;
 | 
| -
 | 
| -  assert(isJsArray(s));
 | 
| -  assert(isJsArray(t));
 | 
| -  assert(getLength(s) == getLength(t));
 | 
| -
 | 
| -  int len = getLength(s);
 | 
| -  for (int i = 0; i < len; i++) {
 | 
| -    if (!isSubtype(getIndex(s, i), getIndex(t, i))) {
 | 
| -      return false;
 | 
| -    }
 | 
| -  }
 | 
| -  return true;
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Computes the signature by applying the type arguments of [context] as an
 | 
| - * instance of [contextName] to the signature function [signature].
 | 
| - */
 | 
| -computeSignature(var signature, var context, var contextName) {
 | 
| -  var typeArguments = getRuntimeTypeArguments(context, contextName);
 | 
| -  return invokeOn(signature, context, typeArguments);
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Returns `true` if the runtime type representation [type] is a supertype of
 | 
| - * [Null].
 | 
| - */
 | 
| -bool isSupertypeOfNull(var type) {
 | 
| -  // `null` means `dynamic`.
 | 
| -  return type == null || isDartObjectTypeRti(type) || isNullTypeRti(type);
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Tests whether the Dart object [o] is a subtype of the runtime type
 | 
| - * representation [t].
 | 
| - *
 | 
| - * See the comment in the beginning of this file for a description of type
 | 
| - * representations.
 | 
| - */
 | 
| -bool checkSubtypeOfRuntimeType(o, t) {
 | 
| -  if (o == null) return isSupertypeOfNull(t);
 | 
| -  if (t == null) return true;
 | 
| -  // Get the runtime type information from the object here, because we may
 | 
| -  // overwrite o with the interceptor below.
 | 
| -  var rti = getRuntimeTypeInfo(o);
 | 
| -  o = getInterceptor(o);
 | 
| -  var type = getRawRuntimeType(o);
 | 
| -  if (rti != null) {
 | 
| -    // If the type has type variables (that is, `rti != null`), make a copy of
 | 
| -    // the type arguments and insert [o] in the first position to create a
 | 
| -    // compound type representation.
 | 
| -    rti = JS('JSExtendableArray', '#.slice()', rti);  // Make a copy.
 | 
| -    JS('', '#.splice(0, 0, #)', rti, type);  // Insert type at position 0.
 | 
| -    type = rti;
 | 
| -  }
 | 
| -  if (isDartFunctionType(t)) {
 | 
| -    // Functions are treated specially and have their type information stored
 | 
| -    // directly in the instance.
 | 
| -    var targetSignatureFunction =
 | 
| -        getField(o, '${JS_GET_NAME(JsGetName.SIGNATURE_NAME)}');
 | 
| -    if (targetSignatureFunction == null) return false;
 | 
| -    type = invokeOn(targetSignatureFunction, o, null);
 | 
| -    return isFunctionSubtype(type, t);
 | 
| -  }
 | 
| -  return isSubtype(type, t);
 | 
| -}
 | 
| -
 | 
| -Object subtypeOfRuntimeTypeCast(Object object, var type) {
 | 
| -  if (object != null && !checkSubtypeOfRuntimeType(object, type)) {
 | 
| -    String actualType = Primitives.objectTypeName(object);
 | 
| -    throw new CastErrorImplementation(actualType, runtimeTypeToString(type));
 | 
| -  }
 | 
| -  return object;
 | 
| -}
 | 
| -
 | 
| -Object assertSubtypeOfRuntimeType(Object object, var type) {
 | 
| -  if (object != null && !checkSubtypeOfRuntimeType(object, type)) {
 | 
| -    throw new TypeErrorImplementation(object, runtimeTypeToString(type));
 | 
| -  }
 | 
| -  return object;
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Extracts the type arguments from a type representation. The result is a
 | 
| - * JavaScript array or `null`.
 | 
| - */
 | 
| -getArguments(var type) {
 | 
| -  return isJsArray(type) ? JS('var', r'#.slice(1)', type) : null;
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Checks whether the type represented by the type representation [s] is a
 | 
| - * subtype of the type represented by the type representation [t].
 | 
| - *
 | 
| - * See the comment in the beginning of this file for a description of type
 | 
| - * representations.
 | 
| - *
 | 
| - * The arguments [s] and [t] must be types, usually represented by the
 | 
| - * constructor of the class, or an array (for generic types).
 | 
| - */
 | 
| -bool isSubtype(var s, var t) {
 | 
| -  // Subtyping is reflexive.
 | 
| -  if (isIdentical(s, t)) return true;
 | 
| -  // If either type is dynamic, [s] is a subtype of [t].
 | 
| -  if (s == null || t == null) return true;
 | 
| -  if (isDartFunctionType(t)) {
 | 
| -    return isFunctionSubtype(s, t);
 | 
| -  }
 | 
| -  // Check function types against the Function class.
 | 
| -  if (isDartFunctionType(s)) {
 | 
| -    return isDartFunctionTypeRti(t);
 | 
| -  }
 | 
| -
 | 
| -  // Get the object describing the class and check for the subtyping flag
 | 
| -  // constructed from the type of [t].
 | 
| -  var typeOfS = isJsArray(s) ? getIndex(s, 0) : s;
 | 
| -  var typeOfT = isJsArray(t) ? getIndex(t, 0) : t;
 | 
| -
 | 
| -  // Check for a subtyping flag.
 | 
| -  // Get the necessary substitution of the type arguments, if there is one.
 | 
| -  var substitution;
 | 
| -  if (isNotIdentical(typeOfT, typeOfS)) {
 | 
| -    if (!builtinIsSubtype(typeOfS, runtimeTypeToString(typeOfT))) {
 | 
| -      return false;
 | 
| -    }
 | 
| -    var typeOfSPrototype = JS('', '#.prototype', typeOfS);
 | 
| -    var field = '${JS_GET_NAME(JsGetName.OPERATOR_AS_PREFIX)}'
 | 
| -        '${runtimeTypeToString(typeOfT)}';
 | 
| -    substitution = getField(typeOfSPrototype, field);
 | 
| -  }
 | 
| -  // The class of [s] is a subclass of the class of [t].  If [s] has no type
 | 
| -  // arguments and no substitution, it is used as raw type.  If [t] has no
 | 
| -  // type arguments, it used as a raw type.  In both cases, [s] is a subtype
 | 
| -  // of [t].
 | 
| -  if ((!isJsArray(s) && substitution == null) || !isJsArray(t)) {
 | 
| -    return true;
 | 
| -  }
 | 
| -  // Recursively check the type arguments.
 | 
| -  return checkArguments(substitution, getArguments(s), getArguments(t));
 | 
| -}
 | 
| -
 | 
| -bool isAssignable(var s, var t) {
 | 
| -  return isSubtype(s, t) || isSubtype(t, s);
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * If [allowShorter] is `true`, [t] is allowed to be shorter than [s].
 | 
| - */
 | 
| -bool areAssignable(List s, List t, bool allowShorter) {
 | 
| -  // Both lists are empty and thus equal.
 | 
| -  if (t ==null && s == null) return true;
 | 
| -  // [t] is empty (and [s] is not) => only OK if [allowShorter].
 | 
| -  if (t == null) return allowShorter;
 | 
| -  // [s] is empty (and [t] is not) => [s] is not longer or equal to [t].
 | 
| -  if (s == null) return false;
 | 
| -
 | 
| -  assert(isJsArray(s));
 | 
| -  assert(isJsArray(t));
 | 
| -
 | 
| -  int sLength = getLength(s);
 | 
| -  int tLength = getLength(t);
 | 
| -  if (allowShorter) {
 | 
| -    if (sLength < tLength) return false;
 | 
| -  } else {
 | 
| -    if (sLength != tLength) return false;
 | 
| -  }
 | 
| -
 | 
| -  for (int i = 0; i < tLength; i++) {
 | 
| -    if (!isAssignable(getIndex(s, i), getIndex(t, i))) {
 | 
| -      return false;
 | 
| -    }
 | 
| -  }
 | 
| -  return true;
 | 
| -}
 | 
| -
 | 
| -bool areAssignableMaps(var s, var t) {
 | 
| -  if (t == null) return true;
 | 
| -  if (s == null) return false;
 | 
| -
 | 
| -  assert(isJsObject(s));
 | 
| -  assert(isJsObject(t));
 | 
| -
 | 
| -  List names =
 | 
| -      JSArray.markFixedList(JS('', 'Object.getOwnPropertyNames(#)', t));
 | 
| -  for (int i = 0; i < names.length; i++) {
 | 
| -    var name = names[i];
 | 
| -    if (JS('bool', '!Object.hasOwnProperty.call(#, #)', s, name)) {
 | 
| -      return false;
 | 
| -    }
 | 
| -    var tType = JS('', '#[#]', t, name);
 | 
| -    var sType = JS('', '#[#]', s, name);
 | 
| -    if (!isAssignable(tType, sType)) return false;
 | 
| -  }
 | 
| -  return true;
 | 
| -}
 | 
| -
 | 
| -bool isFunctionSubtype(var s, var t) {
 | 
| -  assert(isDartFunctionType(t));
 | 
| -  if (!isDartFunctionType(s)) return false;
 | 
| -  var voidReturnTag = JS_GET_NAME(JsGetName.FUNCTION_TYPE_VOID_RETURN_TAG);
 | 
| -  var returnTypeTag = JS_GET_NAME(JsGetName.FUNCTION_TYPE_RETURN_TYPE_TAG);
 | 
| -  if (hasField(s, voidReturnTag)) {
 | 
| -    if (hasNoField(t, voidReturnTag) && hasField(t, returnTypeTag)) {
 | 
| -      return false;
 | 
| -    }
 | 
| -  } else if (hasNoField(t, voidReturnTag)) {
 | 
| -    var sReturnType = getField(s, returnTypeTag);
 | 
| -    var tReturnType = getField(t, returnTypeTag);
 | 
| -    if (!isAssignable(sReturnType, tReturnType)) return false;
 | 
| -  }
 | 
| -  var requiredParametersTag =
 | 
| -      JS_GET_NAME(JsGetName.FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG);
 | 
| -  var sParameterTypes = getField(s, requiredParametersTag);
 | 
| -  var tParameterTypes = getField(t, requiredParametersTag);
 | 
| -
 | 
| -  var optionalParametersTag =
 | 
| -      JS_GET_NAME(JsGetName.FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG);
 | 
| -  var sOptionalParameterTypes = getField(s, optionalParametersTag);
 | 
| -  var tOptionalParameterTypes = getField(t, optionalParametersTag);
 | 
| -
 | 
| -  int sParametersLen = sParameterTypes != null ? getLength(sParameterTypes) : 0;
 | 
| -  int tParametersLen = tParameterTypes != null ? getLength(tParameterTypes) : 0;
 | 
| -
 | 
| -  int sOptionalParametersLen =
 | 
| -      sOptionalParameterTypes != null ? getLength(sOptionalParameterTypes) : 0;
 | 
| -  int tOptionalParametersLen =
 | 
| -      tOptionalParameterTypes != null ? getLength(tOptionalParameterTypes) : 0;
 | 
| -
 | 
| -  if (sParametersLen > tParametersLen) {
 | 
| -    // Too many required parameters in [s].
 | 
| -    return false;
 | 
| -  }
 | 
| -  if (sParametersLen + sOptionalParametersLen <
 | 
| -      tParametersLen + tOptionalParametersLen) {
 | 
| -    // Too few required and optional parameters in [s].
 | 
| -    return false;
 | 
| -  }
 | 
| -  if (sParametersLen == tParametersLen) {
 | 
| -    // Simple case: Same number of required parameters.
 | 
| -    if (!areAssignable(sParameterTypes, tParameterTypes, false)) return false;
 | 
| -    if (!areAssignable(sOptionalParameterTypes,
 | 
| -                       tOptionalParameterTypes, true)) {
 | 
| -      return false;
 | 
| -    }
 | 
| -  } else {
 | 
| -    // Complex case: Optional parameters of [s] for required parameters of [t].
 | 
| -    int pos = 0;
 | 
| -    // Check all required parameters of [s].
 | 
| -    for (; pos < sParametersLen; pos++) {
 | 
| -      if (!isAssignable(getIndex(sParameterTypes, pos),
 | 
| -                        getIndex(tParameterTypes, pos))) {
 | 
| -        return false;
 | 
| -      }
 | 
| -    }
 | 
| -    int sPos = 0;
 | 
| -    int tPos = pos;
 | 
| -    // Check the remaining parameters of [t] with the first optional parameters
 | 
| -    // of [s].
 | 
| -    for (; tPos < tParametersLen ; sPos++, tPos++) {
 | 
| -      if (!isAssignable(getIndex(sOptionalParameterTypes, sPos),
 | 
| -                        getIndex(tParameterTypes, tPos))) {
 | 
| -        return false;
 | 
| -      }
 | 
| -    }
 | 
| -    tPos = 0;
 | 
| -    // Check the optional parameters of [t] with the remaining optional
 | 
| -    // parameters of [s]:
 | 
| -    for (; tPos < tOptionalParametersLen ; sPos++, tPos++) {
 | 
| -      if (!isAssignable(getIndex(sOptionalParameterTypes, sPos),
 | 
| -                        getIndex(tOptionalParameterTypes, tPos))) {
 | 
| -        return false;
 | 
| -      }
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  var namedParametersTag =
 | 
| -      JS_GET_NAME(JsGetName.FUNCTION_TYPE_NAMED_PARAMETERS_TAG);
 | 
| -  var sNamedParameters = getField(s, namedParametersTag);
 | 
| -  var tNamedParameters = getField(t, namedParametersTag);
 | 
| -  return areAssignableMaps(sNamedParameters, tNamedParameters);
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Calls the JavaScript [function] with the [arguments] with the global scope
 | 
| - * as the `this` context.
 | 
| - */
 | 
| -invoke(var function, var arguments) => invokeOn(function, null, arguments);
 | 
| -
 | 
| -/**
 | 
| - * Calls the JavaScript [function] with the [arguments] with [receiver] as the
 | 
| - * `this` context.
 | 
| - */
 | 
| -Object invokeOn(function, receiver, arguments) {
 | 
| -  assert(isJsFunction(function));
 | 
| -  assert(arguments == null || isJsArray(arguments));
 | 
| -  return JS('var', r'#.apply(#, #)', function, receiver, arguments);
 | 
| -}
 | 
| -
 | 
| -/// Calls the property [name] on the JavaScript [object].
 | 
| -call(var object, String name) => JS('var', r'#[#]()', object, name);
 | 
| -
 | 
| -/// Returns the property [name] of the JavaScript object [object].
 | 
| -getField(var object, String name) => JS('var', r'#[#]', object, name);
 | 
| -
 | 
| -/// Returns the property [index] of the JavaScript array [array].
 | 
| -getIndex(var array, int index) {
 | 
| -  assert(isJsArray(array));
 | 
| -  return JS('var', r'#[#]', array, index);
 | 
| -}
 | 
| -
 | 
| -/// Returns the length of the JavaScript array [array].
 | 
| -int getLength(var array) {
 | 
| -  assert(isJsArray(array));
 | 
| -  return JS('int', r'#.length', array);
 | 
| -}
 | 
| -
 | 
| -/// Returns whether [value] is a JavaScript array.
 | 
| -bool isJsArray(var value) {
 | 
| -  return value is JSArray;
 | 
| -}
 | 
| -
 | 
| -hasField(var object, var name) => JS('bool', r'# in #', name, object);
 | 
| -
 | 
| -hasNoField(var object, var name) => !hasField(object, name);
 | 
| -
 | 
| -/// Returns `true` if [o] is a JavaScript function.
 | 
| -bool isJsFunction(var o) => JS('bool', r'typeof # == "function"', o);
 | 
| -
 | 
| -/// Returns `true` if [o] is a JavaScript object.
 | 
| -bool isJsObject(var o) => JS('bool', r"typeof # == 'object'", o);
 | 
| -
 | 
| -/**
 | 
| - * Returns `true` if the JavaScript values [s] and [t] are identical. We use
 | 
| - * this helper instead of [identical] because `identical` needs to merge
 | 
| - * `null` and `undefined` (which we can avoid).
 | 
| - */
 | 
| -bool isIdentical(var s, var t) => JS('bool', '# === #', s, t);
 | 
| -
 | 
| -/**
 | 
| - * Returns `true` if the JavaScript values [s] and [t] are not identical. We use
 | 
| - * this helper instead of [identical] because `identical` needs to merge
 | 
| - * `null` and `undefined` (which we can avoid).
 | 
| - */
 | 
| -bool isNotIdentical(var s, var t) => JS('bool', '# !== #', s, t);
 | 
| 
 |