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 |