| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library _js_helper; | 5 library _js_helper; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 import 'dart:_foreign_helper' show DART_CLOSURE_TO_JS, | 8 import 'dart:_foreign_helper' show DART_CLOSURE_TO_JS, |
| 9 JS, | 9 JS, |
| 10 JS_CALL_IN_ISOLATE, | 10 JS_CALL_IN_ISOLATE, |
| (...skipping 1523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1534 } | 1534 } |
| 1535 } | 1535 } |
| 1536 return true; | 1536 return true; |
| 1537 } | 1537 } |
| 1538 | 1538 |
| 1539 getArguments(var type) => JS('var', r'#.slice(1)', type); | 1539 getArguments(var type) => JS('var', r'#.slice(1)', type); |
| 1540 | 1540 |
| 1541 getField(var object, var name) => JS('var', r'#[#]', object, name); | 1541 getField(var object, var name) => JS('var', r'#[#]', object, name); |
| 1542 | 1542 |
| 1543 /** | 1543 /** |
| 1544 * Tests whether the Dart object [o] is a subtype of the runtime type |
| 1545 * representation [t], which is a type representation as described in the |
| 1546 * comment on [isSubtype]. |
| 1547 */ |
| 1548 bool objectIsSubtype(Object o, var t) { |
| 1549 if (JS('bool', '# == null', o) || JS('bool', '# == null', t)) return true; |
| 1550 // In the case of [List], [t] will be an array with the type representation |
| 1551 // in the first entry and the type argument in the second. |
| 1552 var typeOfT = isJsArray(t) ? getField(t, 0) : t; |
| 1553 var nativeCheck = getField(typeOfT, '\$nativeCheck'); |
| 1554 if (nativeCheck != null) { |
| 1555 bool isInstance = invoke(nativeCheck, [o]); |
| 1556 if (!isInstance) return false; |
| 1557 if (o is List) { |
| 1558 // If the object is a list and passed the native check, we know that [t] |
| 1559 // is an array containing the type argument as its second entry. |
| 1560 return isSubtype(getRuntimeTypeArgument(o, null, 0), getField(t, 1)); |
| 1561 } |
| 1562 return true; |
| 1563 } else { |
| 1564 var type; |
| 1565 var rti = getRuntimeTypeInfo(o); |
| 1566 // If the type has type variables (that is, [:rti != null:]), make a copy of |
| 1567 // the type arguments and insert [o] in the first position to create a |
| 1568 // compound type representation, otherwise use [o] itself. |
| 1569 if (JS('bool', '# != null', rti)) { |
| 1570 type = JS('List', '#.slice().splice(0, 0, #)', rti, o); |
| 1571 } else { |
| 1572 // We can use the object as its own type representation because we install |
| 1573 // the subtype flags and the substitution on the prototype, so they are |
| 1574 // properties of the object in JS. |
| 1575 type = o; |
| 1576 } |
| 1577 return isSubtype(type, t); |
| 1578 } |
| 1579 } |
| 1580 |
| 1581 |
| 1582 /** |
| 1544 * Check whether the type represented by [s] is a subtype of the type | 1583 * Check whether the type represented by [s] is a subtype of the type |
| 1545 * represented by [t]. | 1584 * represented by [t]. |
| 1546 * | 1585 * |
| 1547 * Type representations can be: | 1586 * Type representations can be: |
| 1548 * 1) a JavaScript constructor for a class C: the represented type is the raw | 1587 * 1) a JavaScript constructor for a class C: the represented type is the raw |
| 1549 * type C. | 1588 * type C. |
| 1550 * 2) a JavaScript object: this represents a class for which there is no | 1589 * 2) a Dart object. |
| 1590 * 3) a JavaScript object: this represents a class for which there is no |
| 1551 * JavaScript constructor, because it is only used in type arguments or it | 1591 * JavaScript constructor, because it is only used in type arguments or it |
| 1552 * is native. The represented type is the raw type of this class. | 1592 * is native. The represented type is the raw type of this class. |
| 1553 * 3) a JavaScript array: the first entry is of type 1 or 2 and identifies the | 1593 * 4) a JavaScript array: the first entry is of type 1, 2 or 3 and contains the |
| 1554 * class of the type and the rest of the array are the type arguments. | 1594 * subtyping flags and the substitution of the type and the rest of the |
| 1555 * 4) [:null:]: the dynamic type. | 1595 * array are the type arguments. |
| 1596 * 5) [:null:]: the dynamic type. |
| 1556 */ | 1597 */ |
| 1557 bool isSubtype(var s, var t) { | 1598 bool isSubtype(var s, var t) { |
| 1558 // If either type is dynamic, [s] is a subtype of [t]. | 1599 // If either type is dynamic, [s] is a subtype of [t]. |
| 1559 if (JS('bool', '# == null', s) || JS('bool', '# == null', t)) return true; | 1600 if (JS('bool', '# == null', s) || JS('bool', '# == null', t)) return true; |
| 1560 // Subtyping is reflexive. | 1601 // Subtyping is reflexive. |
| 1561 if (JS('bool', '# === #', s, t)) return true; | 1602 if (JS('bool', '# === #', s, t)) return true; |
| 1562 // Get the object describing the class and check for the subtyping flag | 1603 // Get the object describing the class and check for the subtyping flag |
| 1563 // constructed from the type of [t]. | 1604 // constructed from the type of [t]. |
| 1564 var typeOfS = isJsArray(s) ? s[0] : s; | 1605 var typeOfS = isJsArray(s) ? s[0] : s; |
| 1565 var typeOfT = isJsArray(t) ? t[0] : t; | 1606 var typeOfT = isJsArray(t) ? t[0] : t; |
| 1566 // Check for a subtyping flag. | 1607 // Check for a subtyping flag. |
| 1567 var test = '${JS_OPERATOR_IS_PREFIX()}${runtimeTypeToString(typeOfT)}'; | 1608 var test = '${JS_OPERATOR_IS_PREFIX()}${runtimeTypeToString(typeOfT)}'; |
| 1568 if (getField(typeOfS, test) == null) return false; | 1609 if (getField(typeOfS, test) == null) return false; |
| 1569 // The class of [s] is a subclass of the class of [t]. If either of the types | 1610 // The class of [s] is a subclass of the class of [t]. If either of the types |
| 1570 // is raw, [s] is a subtype of [t]. | 1611 // is raw, [s] is a subtype of [t]. |
| 1571 if (!isJsArray(s) || !isJsArray(t)) return true; | 1612 if (!isJsArray(s) || !isJsArray(t)) return true; |
| 1572 // Get the necessary substitution of the type arguments, if there is one. | 1613 // Get the necessary substitution of the type arguments, if there is one. |
| 1573 var substitution; | 1614 var substitution; |
| 1574 if (JS('bool', '# !== #', typeOfT, typeOfS)) { | 1615 if (JS('bool', '# !== #', typeOfT, typeOfS)) { |
| 1575 var field = '${JS_OPERATOR_AS_PREFIX()}${runtimeTypeToString(typeOfT)}'; | 1616 var field = '${JS_OPERATOR_AS_PREFIX()}${runtimeTypeToString(typeOfT)}'; |
| 1576 substitution = getField(typeOfS, field); | 1617 substitution = getField(typeOfS, field); |
| 1577 } | 1618 } |
| 1578 // Recursively check the type arguments. | 1619 // Recursively check the type arguments. |
| 1579 return checkArguments(substitution, getArguments(s), getArguments(t)); | 1620 return checkArguments(substitution, getArguments(s), getArguments(t)); |
| 1580 } | 1621 } |
| 1581 | 1622 |
| 1582 createRuntimeType(String name) => new TypeImpl(name); | 1623 createRuntimeType(String name) => new TypeImpl(name); |
| OLD | NEW |