Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 /// This library defines the association between runtime objects and | 5 /// This library defines the association between runtime objects and |
| 6 /// runtime types. | 6 /// runtime types. |
| 7 part of dart._runtime; | 7 part of dart._runtime; |
| 8 | 8 |
| 9 /// | |
| 10 /// Runtime type information. This module defines the mapping from | 9 /// Runtime type information. This module defines the mapping from |
| 11 /// runtime objects to their runtime type information. See the types | 10 /// runtime objects to their runtime type information. See the types |
| 12 /// module for the definition of how type information is represented. | 11 /// module for the definition of how type information is represented. |
| 13 /// | 12 /// |
| 14 /// Runtime objects fall into four main categories: | 13 /// There are two kinds of objects that represent "types" at runtime. A |
| 14 /// "runtime type" contains all of the data needed to implement the runtime | |
| 15 /// type checking inserted by the compiler. These objects fall into four | |
| 16 /// categories: | |
| 15 /// | 17 /// |
| 16 /// - Things represented by javascript primitives, such as | 18 /// - Things represented by javascript primitives, such as |
| 17 /// null, numbers, booleans, strings, and symbols. For these | 19 /// null, numbers, booleans, strings, and symbols. For these |
| 18 /// we map directly from the javascript type (given by typeof) | 20 /// we map directly from the javascript type (given by typeof) |
| 19 /// to the appropriate class type from core, which serves as their | 21 /// to the appropriate class type from core, which serves as their |
| 20 /// rtti. | 22 /// rtti. |
| 21 /// | 23 /// |
| 22 /// - Functions, which are represented by javascript functions. | 24 /// - Functions, which are represented by javascript functions. |
| 23 /// Representations of Dart functions always have a | 25 /// Representations of Dart functions always have a |
| 24 /// _runtimeType property attached to them with the appropriate | 26 /// _runtimeType property attached to them with the appropriate |
| 25 /// rtti. | 27 /// rtti. |
| 26 /// | 28 /// |
| 27 /// - Objects (instances) which are represented by instances of | 29 /// - Objects (instances) which are represented by instances of |
| 28 /// javascript (ES6) classes. Their types are given by their | 30 /// javascript (ES6) classes. Their types are given by their |
| 29 /// classes, and the rtti is accessed by projecting out their | 31 /// classes, and the rtti is accessed by projecting out their |
| 30 /// constructor field. | 32 /// constructor field. |
| 31 /// | 33 /// |
| 32 /// - Types objects, which are represented as described in the types | 34 /// - Types objects, which are represented as described in the types |
| 33 /// module. Types always have a _runtimeType property attached to | 35 /// module. Types always have a _runtimeType property attached to |
| 34 /// them with the appropriate rtti. The rtti for these is always | 36 /// them with the appropriate rtti. The rtti for these is always |
| 35 /// core.Type. TODO(leafp): consider the possibility that we can | 37 /// core.Type. TODO(leafp): consider the possibility that we can |
| 36 /// reliably recognize type objects and map directly to core.Type | 38 /// reliably recognize type objects and map directly to core.Type |
| 37 /// rather than attaching this property everywhere. | 39 /// rather than attaching this property everywhere. |
| 38 /// | 40 /// |
| 39 /// | 41 /// The other kind of object representing a "type" is the instances of the |
| 42 /// dart:core Type class. These are the user visible objects you get by calling | |
| 43 /// "runtimeType" on an object or using a class literal expression. These are | |
| 44 /// different from the above objects, and are created by calling `wrapType()` | |
| 45 /// on a runtime type. | |
| 40 | 46 |
| 41 /// | 47 /// Tags a closure with a type, using one of three forms: |
| 42 ///Tag a closure with a type, using one of three forms: | |
| 43 /// dart.fn(cls) marks cls has having no optional or named | 48 /// dart.fn(cls) marks cls has having no optional or named |
| 44 /// parameters, with all argument and return types as dynamic | 49 /// parameters, with all argument and return types as dynamic |
| 45 /// dart.fn(cls, func) marks cls with the lazily computed | 50 /// dart.fn(cls, func) marks cls with the lazily computed |
| 46 /// runtime type as computed by func() | 51 /// runtime type as computed by func() |
| 47 /// dart.fn(cls, rType, argsT, extras) marks cls as having the | 52 /// dart.fn(cls, rType, argsT, extras) marks cls as having the |
| 48 /// runtime type dart.functionType(rType, argsT, extras) | 53 /// runtime type dart.functionType(rType, argsT, extras) |
| 49 /// | 54 /// |
| 50 /// Note that since we are producing a type for a concrete function, | 55 /// Note that since we are producing a type for a concrete function, |
| 51 /// it is sound to use the definite arrow type. | 56 /// it is sound to use the definite arrow type. |
| 52 /// | 57 /// |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 86 case "symbol": | 91 case "symbol": |
| 87 return Symbol; | 92 return Symbol; |
| 88 } | 93 } |
| 89 // Undefined is handled above. For historical reasons, | 94 // Undefined is handled above. For historical reasons, |
| 90 // typeof null == "object" in JS. | 95 // typeof null == "object" in JS. |
| 91 if ($obj === null) return $Null; | 96 if ($obj === null) return $Null; |
| 92 return null; | 97 return null; |
| 93 })()'''); | 98 })()'''); |
| 94 | 99 |
| 95 runtimeType(obj) => JS('', '''(() => { | 100 runtimeType(obj) => JS('', '''(() => { |
| 96 // Lookup primitive (int/double/string) | 101 // Handle primitives where the method isn't on the object. |
| 97 let result = $checkPrimitiveType($obj); | 102 let result = $checkPrimitiveType($obj); |
| 98 if (result !== null) return result; | 103 if (result !== null) return $wrapType(result); |
| 99 | 104 |
| 100 // Lookup recorded type | 105 // Delegate to the actual method on the object. |
|
Jennifer Messerly
2016/05/02 23:04:20
it might be worth a comment/TODO here, this issue
| |
| 101 result = $obj.runtimeType; | 106 return $obj.runtimeType; |
| 102 if (result) return result; | |
| 103 | |
| 104 return $_nonPrimitiveRuntimeType(obj); | |
| 105 })()'''); | 107 })()'''); |
| 106 | 108 |
| 107 getFunctionType(obj) => JS('', '''(() => { | 109 getFunctionType(obj) => JS('', '''(() => { |
| 108 // TODO(vsm): Encode this properly on the function for Dart-generated code. | 110 // TODO(vsm): Encode this properly on the function for Dart-generated code. |
| 109 let args = Array($obj.length).fill($dynamicR); | 111 let args = Array($obj.length).fill($dynamicR); |
| 110 return $definiteFunctionType($bottom, args); | 112 return $definiteFunctionType($bottom, args); |
| 111 })()'''); | 113 })()'''); |
| 112 | 114 |
| 115 /// The base implementation of Object.runtimeType. | |
| 116 objectRuntimeType(obj) => JS('', '''(() => { | |
|
Jennifer Messerly
2016/05/02 23:04:20
Hey so I've been trying to clean these up. You can
Bob Nystrom
2016/05/03 20:50:47
Done.
| |
| 117 return $wrapType($getReifiedType($obj)); | |
| 118 })()'''); | |
| 119 | |
| 120 /// Returns an the runtime representation of the type of obj. | |
| 113 /// | 121 /// |
| 114 /// Returns the runtime type of obj. This is the same as `obj.realRuntimeType` | 122 /// The resulting object is used internally for runtime type checking. This is |
| 115 /// but will not call an overridden getter. | 123 /// different from the user-visible Type object returned by calling |
| 116 /// | 124 /// `runtimeType` on some Dart object. |
| 117 /// Currently this will return null for non-Dart objects. | 125 getReifiedType(obj) => JS('', '''(() => { |
|
Jennifer Messerly
2016/05/02 23:04:20
if you feel like it -- cleanup idea :)
getReified
Bob Nystrom
2016/05/03 20:50:47
Done.
| |
| 118 /// | |
| 119 realRuntimeType(obj) => JS('', '''(() => { | |
| 120 // Lookup primitive type | 126 // Lookup primitive type |
| 121 let result = $checkPrimitiveType($obj); | 127 let result = $checkPrimitiveType($obj); |
| 122 if (result !== null) return result; | 128 if (result !== null) return result; |
| 123 | 129 |
| 124 return $_nonPrimitiveRuntimeType(obj); | 130 return $_nonPrimitiveRuntimeType(obj); |
| 125 })()'''); | 131 })()'''); |
| 126 | 132 |
| 127 _nonPrimitiveRuntimeType(obj) => JS('', '''(() => { | 133 _nonPrimitiveRuntimeType(obj) => JS('', '''(() => { |
| 128 // Lookup recorded *real* type (not user definable runtimeType) | 134 // Lookup recorded *real* type (not user definable runtimeType) |
| 129 // TODO(vsm): Should we treat Dart and JS objects differently here? | 135 // TODO(vsm): Should we treat Dart and JS objects differently here? |
| 130 // E.g., we can check if obj instanceof core.Object to differentiate. | 136 // E.g., we can check if obj instanceof core.Object to differentiate. |
| 131 let result = $obj[$_runtimeType]; | 137 let result = $obj[$_runtimeType]; |
| 132 if (result) return result; | 138 if (result) return result; |
| 133 | 139 |
| 134 // Lookup extension type | 140 // Lookup extension type |
| 135 result = $obj[$_extensionType]; | 141 result = $obj[$_extensionType]; |
| 136 if (result) return result; | 142 if (result) return result; |
| 137 | 143 |
| 138 // Fallback on constructor for class types | 144 // Fallback on constructor for class types |
| 139 result = $obj.constructor; | 145 result = $obj.constructor; |
| 140 if (result == Function) { | 146 if (result == Function) { |
| 141 // An undecorated Function should have come from | 147 // An undecorated Function should have come from |
| 142 // JavaScript. Treat as untyped. | 148 // JavaScript. Treat as untyped. |
| 143 return $jsobject; | 149 return $jsobject; |
| 144 } | 150 } |
| 145 return result; | 151 return result; |
| 146 })()'''); | 152 })()'''); |
| 147 | 153 |
| 154 /// Given an internal runtime type object, wraps it in a `WrappedType` object | |
| 155 /// that implements the dart:core Type interface. | |
| 156 wrapType(type) => JS('', '''(() => { | |
|
Jennifer Messerly
2016/05/02 23:04:20
nowadays we'd write this more like:
wrapType(type
Bob Nystrom
2016/05/03 20:50:47
Done.
| |
| 157 // If we've already wrapped this type once, use the previous wrapper. This | |
| 158 // way, multiple references to the same type return an identical Type. | |
| 159 if ($type.hasOwnProperty($_typeObject)) { | |
| 160 return $type[$_typeObject]; | |
| 161 } | |
| 162 | |
| 163 return $type[$_typeObject] = new $WrappedType($type); | |
| 164 })()'''); | |
| 165 | |
| 148 read(value) => JS('', '#[#]', value, _runtimeType); | 166 read(value) => JS('', '#[#]', value, _runtimeType); |
| 149 | 167 |
| 150 /// Tag the runtime type of [value] to be type [t]. | 168 /// Tag the runtime type of [value] to be type [t]. |
| 151 void tag(value, t) { | 169 void tag(value, t) { |
| 152 JS('', '#[#] = #', value, _runtimeType, t); | 170 JS('', '#[#] = #', value, _runtimeType, t); |
| 153 } | 171 } |
| 154 | 172 |
| 155 tagComputed(value, compute) { | 173 tagComputed(value, compute) { |
| 156 JS('', '#(#, #, { get: # })', defineProperty, value, _runtimeType, compute); | 174 JS('', '#(#, #, { get: # })', defineProperty, value, _runtimeType, compute); |
| 157 } | 175 } |
| 158 | 176 |
| 159 tagMemoized(value, compute) => JS('', '''(() => { | 177 tagMemoized(value, compute) => JS('', '''(() => { |
| 160 let cache = null; | 178 let cache = null; |
| 161 function getter() { | 179 function getter() { |
| 162 if ($compute == null) return cache; | 180 if ($compute == null) return cache; |
| 163 cache = $compute(); | 181 cache = $compute(); |
| 164 $compute = null; | 182 $compute = null; |
| 165 return cache; | 183 return cache; |
| 166 } | 184 } |
| 167 $tagComputed($value, getter); | 185 $tagComputed($value, getter); |
| 168 })()'''); | 186 })()'''); |
| OLD | NEW |