| Index: sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
|
| diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
|
| index bf78d1a4ab852bb297aa33c1f7df69472ef99df7..f00396a10e6eaaef4eb4acea392af235bbfecdc4 100644
|
| --- a/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
|
| +++ b/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
|
| @@ -1535,23 +1535,61 @@ bool areSubtypes(List s, List t) {
|
| return true;
|
| }
|
|
|
| -getArguments(var type) => JS('var', r'#.slice(1)', type);
|
| +getArguments(var type) {
|
| + return isJsArray(type) ? JS('var', r'#.slice(1)', type) : null;
|
| +}
|
|
|
| getField(var object, var name) => JS('var', r'#[#]', object, name);
|
|
|
| /**
|
| + * Tests whether the Dart object [o] is a subtype of the runtime type
|
| + * representation [t], which is a type representation as described in the
|
| + * comment on [isSubtype].
|
| + */
|
| +bool objectIsSubtype(Object o, var t) {
|
| + if (JS('bool', '# == null', o) || JS('bool', '# == null', t)) return true;
|
| + // Get the runtime type information from the object here, because we may
|
| + // overwrite o with the interceptor below.
|
| + var rti = getRuntimeTypeInfo(o);
|
| + // Check for native objects and use the interceptor instead of the object.
|
| + var interceptor = getInterceptor(o);
|
| + // TODO(karlklose): remove the following reuse of _objectInterceptor.
|
| + if (!identical(interceptor, JSInvocationMirror._objectInterceptor)) {
|
| + o = interceptor;
|
| + }
|
| + // We can use the object as its own type representation because we install
|
| + // the subtype flags and the substitution on the prototype, so they are
|
| + // properties of the object in JS.
|
| + var type;
|
| + if (JS('bool', '# != null', rti)) {
|
| + // 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.
|
| + type = JS('List', '#.slice()', rti);
|
| + JS('', '#.splice(0, 0, #)', type, o);
|
| + } else {
|
| + // Use the object as representation of the raw type.
|
| + type = o;
|
| + }
|
| + return isSubtype(type, t);
|
| +}
|
| +
|
| +
|
| +/**
|
| * Check whether the type represented by [s] is a subtype of the type
|
| * represented by [t].
|
| *
|
| * Type representations can be:
|
| * 1) a JavaScript constructor for a class C: the represented type is the raw
|
| * type C.
|
| - * 2) a JavaScript object: this represents a class for which there is no
|
| + * 2) a Dart object: this is the interceptor instance for a native type.
|
| + * 3) a JavaScript object: this represents a class for which there is no
|
| * JavaScript constructor, because it is only used in type arguments or it
|
| * is native. The represented type is the raw type of this class.
|
| - * 3) a JavaScript array: the first entry is of type 1 or 2 and identifies the
|
| - * class of the type and the rest of the array are the type arguments.
|
| - * 4) [:null:]: the dynamic type.
|
| + * 4) a JavaScript array: the first entry is of type 1, 2 or 3 and contains the
|
| + * subtyping flags and the substitution of the type and the rest of the
|
| + * array are the type arguments.
|
| + * 5) [:null:]: the dynamic type.
|
| */
|
| bool isSubtype(var s, var t) {
|
| // If either type is dynamic, [s] is a subtype of [t].
|
| @@ -1565,15 +1603,20 @@ bool isSubtype(var s, var t) {
|
| // Check for a subtyping flag.
|
| var test = '${JS_OPERATOR_IS_PREFIX()}${runtimeTypeToString(typeOfT)}';
|
| if (getField(typeOfS, test) == null) return false;
|
| - // The class of [s] is a subclass of the class of [t]. If either of the types
|
| - // is raw, [s] is a subtype of [t].
|
| - if (!isJsArray(s) || !isJsArray(t)) return true;
|
| // Get the necessary substitution of the type arguments, if there is one.
|
| var substitution;
|
| if (JS('bool', '# !== #', typeOfT, typeOfS)) {
|
| var field = '${JS_OPERATOR_AS_PREFIX()}${runtimeTypeToString(typeOfT)}';
|
| substitution = getField(typeOfS, 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) && JS('bool', '# == null', substitution)) ||
|
| + !isJsArray(t)) {
|
| + return true;
|
| + }
|
| // Recursively check the type arguments.
|
| return checkArguments(substitution, getArguments(s), getArguments(t));
|
| }
|
|
|