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 |
index ce595394166a6b007438b8e57a199033445d1b2f..08c52dd960e7d83d819a8576b981035b8a8cf6e8 100644 |
--- a/sdk/lib/_internal/compiler/js_lib/js_rti.dart |
+++ b/sdk/lib/_internal/compiler/js_lib/js_rti.dart |
@@ -390,17 +390,24 @@ bool checkSubtypeOfRuntimeType(o, t) { |
// overwrite o with the interceptor below. |
var rti = getRuntimeTypeInfo(o); |
o = getInterceptor(o); |
- // We can use the object as its own type representation because we install |
- var type; |
+ var type = JS('', '#.constructor', 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. |
- type = JS('JSExtendableArray', '#.slice()', rti); |
- JS('', '#.splice(0, 0, #)', type, o); |
- } else { |
- // Use the object as representation of the raw type. |
- type = o; |
+ rti = JS('JSExtendableArray', '#.slice()', rti); // Make a copy. |
+ JS('', '#.splice(0, 0, #)', rti, type); // Insert type at position 0. |
+ type = rti; |
+ } else if (hasField(t, '${JS_FUNCTION_TYPE_TAG()}')) { |
+ // Functions are treated specially and have their type information stored |
+ // directly in the instance. |
+ var signatureName = |
+ '${JS_OPERATOR_IS_PREFIX()}_${getField(t, JS_FUNCTION_TYPE_TAG())}'; |
+ if (hasField(o, signatureName)) return true; |
+ var targetSignatureFunction = getField(o, '${JS_SIGNATURE_NAME()}'); |
+ if (targetSignatureFunction == null) return false; |
+ type = invokeOn(targetSignatureFunction, o, null); |
+ return isFunctionSubtype(type, t); |
} |
return isSubtype(type, t); |
} |
@@ -434,6 +441,9 @@ getArguments(var type) { |
* |
* 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. |
@@ -441,21 +451,13 @@ bool isSubtype(var s, var t) { |
// If either type is dynamic, [s] is a subtype of [t]. |
if (s == null || t == null) return true; |
if (hasField(t, '${JS_FUNCTION_TYPE_TAG()}')) { |
- if (hasNoField(s, '${JS_FUNCTION_TYPE_TAG()}')) { |
- var signatureName = |
- '${JS_OPERATOR_IS_PREFIX()}_${getField(t, JS_FUNCTION_TYPE_TAG())}'; |
- if (hasField(s, signatureName)) return true; |
- var targetSignatureFunction = getField(s, '${JS_SIGNATURE_NAME()}'); |
- if (targetSignatureFunction == null) return false; |
- s = invokeOn(targetSignatureFunction, s, null); |
- } |
return isFunctionSubtype(s, t); |
} |
// Check function types against the Function class. |
- if (getConstructorName(t) == JS_FUNCTION_CLASS_NAME() && |
- hasField(s, '${JS_FUNCTION_TYPE_TAG()}')) { |
- return true; |
+ if (hasField(s, '${JS_FUNCTION_TYPE_TAG()}')) { |
+ return getConstructorName(t) == JS_FUNCTION_CLASS_NAME(); |
} |
+ |
// 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; |
@@ -466,9 +468,10 @@ bool isSubtype(var s, var t) { |
var substitution; |
if (isNotIdentical(typeOfT, typeOfS)) { |
var test = '${JS_OPERATOR_IS_PREFIX()}${name}'; |
- if (hasNoField(typeOfS, test)) return false; |
+ var typeOfSPrototype = JS('', '#.prototype', typeOfS); |
+ if (hasNoField(typeOfSPrototype, test)) return false; |
var field = '${JS_OPERATOR_AS_PREFIX()}${runtimeTypeToString(typeOfT)}'; |
- substitution = getField(typeOfS, field); |
+ 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 |