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 /// Runtime type information. This module defines the mapping from | 9 /// Runtime type information. This module defines the mapping from |
10 /// runtime objects to their runtime type information. See the types | 10 /// runtime objects to their runtime type information. See the types |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
68 lazyFn(closure, computeType) { | 68 lazyFn(closure, computeType) { |
69 tagLazy(closure, computeType); | 69 tagLazy(closure, computeType); |
70 return closure; | 70 return closure; |
71 } | 71 } |
72 | 72 |
73 // TODO(vsm): How should we encode the runtime type? | 73 // TODO(vsm): How should we encode the runtime type? |
74 final _runtimeType = JS('', 'Symbol("_runtimeType")'); | 74 final _runtimeType = JS('', 'Symbol("_runtimeType")'); |
75 | 75 |
76 final _moduleName = JS('', 'Symbol("_moduleName")'); | 76 final _moduleName = JS('', 'Symbol("_moduleName")'); |
77 | 77 |
78 _checkPrimitiveType(obj) { | |
79 // TODO(jmesserly): JS is used to prevent type literal wrapping. Is there a | |
80 // better way we can handle this? (sra: It is super dodgy that the values | |
81 // passed to JS are different to the values passed to a regular function - the | |
82 // semantics are not longer that of calling an interpreter. dart2js has other | |
83 // special functions, we could do the same.) | |
84 | |
85 // Check for null and undefined | |
86 if (obj == null) return JS('', '#', Null); | |
87 | |
88 if (JS('bool', 'typeof # == "number"', obj)) { | |
89 if (JS('bool', 'Math.floor(#) == #', obj, obj)) { | |
90 return JS('', '#', int); | |
91 } | |
92 return JS('', '#', double); | |
93 } | |
94 | |
95 if (JS('bool', 'typeof # == "boolean"', obj)) { | |
96 return JS('', '#', bool); | |
97 } | |
98 | |
99 if (JS('bool', 'typeof # == "string"', obj)) { | |
100 return JS('', '#', String); | |
101 } | |
102 | |
103 if (JS('bool', 'typeof # == "symbol"', obj)) { | |
104 // Note: this is a JS Symbol, not a Dart one. | |
105 return JS('', '#', jsobject); | |
106 } | |
107 | |
108 return null; | |
109 } | |
110 | |
111 getFunctionType(obj) { | 78 getFunctionType(obj) { |
112 // TODO(vsm): Encode this properly on the function for Dart-generated code. | 79 // TODO(vsm): Encode this properly on the function for Dart-generated code. |
113 var args = JS('List', 'Array(#.length).fill(#)', obj, dynamic); | 80 var args = JS('List', 'Array(#.length).fill(#)', obj, dynamic); |
114 return fnType(bottom, args, JS('', 'void 0')); | 81 return fnType(bottom, args, JS('', 'void 0')); |
115 } | 82 } |
116 | 83 |
117 /// Returns the runtime representation of the type of obj. | 84 /// Returns the runtime representation of the type of obj. |
118 /// | 85 /// |
119 /// The resulting object is used internally for runtime type checking. This is | 86 /// The resulting object is used internally for runtime type checking. This is |
120 /// different from the user-visible Type object returned by calling | 87 /// different from the user-visible Type object returned by calling |
121 /// `runtimeType` on some Dart object. | 88 /// `runtimeType` on some Dart object. |
122 getReifiedType(obj) { | 89 getReifiedType(obj) { |
123 var result = _checkPrimitiveType(obj); | 90 switch (JS('String', 'typeof #', obj)) { |
Leaf
2017/08/24 17:19:39
Will V8 make this code fast, even when the `typeof
Jennifer Messerly
2017/08/24 18:26:37
Yup. I was skeptical too, but this code was the re
| |
124 if (result != null) return result; | 91 case "object": |
125 return _nonPrimitiveRuntimeType(obj); | 92 if (obj == null) return JS('', '#', Null); |
126 } | 93 if (JS('bool', '# instanceof #', obj, Object)) { |
127 | 94 return JS('', '#.constructor', obj); |
128 /// Assumes that obj is non-null | 95 } |
129 _nonPrimitiveRuntimeType(obj) { | 96 var result = JS('', '#[#]', obj, _extensionType); |
130 // Lookup recorded *real* type (not user definable runtimeType) | 97 if (result == null) return JS('', '#', jsobject); |
Jennifer Messerly
2017/08/23 23:36:01
FYI -- there's one subtle difference from the old
Leaf
2017/08/24 17:19:39
Acknowledged.
| |
131 // TODO(vsm): Should we treat Dart and JS objects differently here? | 98 return result; |
132 // E.g., we can check if obj instanceof core.Object to differentiate. | 99 case "function": |
133 var result = _getRuntimeType(obj); | 100 // All Dart functions and callable classes must set _runtimeType |
134 if (result != null) return result; | 101 var result = JS('', '#[#]', obj, _runtimeType); |
135 | 102 if (result != null) return result; |
136 // Lookup extension type | 103 return JS('', '#', jsobject); |
137 result = getExtensionType(obj); | 104 case "undefined": |
138 if (result != null) return result; | 105 return JS('', '#', Null); |
139 | 106 case "number": |
140 // Fallback on constructor for class types | 107 return JS('', 'Math.floor(#) == # ? # : #', obj, obj, int, double); |
141 result = JS('', '#.constructor', obj); | 108 case "boolean": |
142 if (JS('bool', '# === Function', result)) { | 109 return JS('', '#', bool); |
143 // An undecorated Function should have come from JavaScript. | 110 case "string": |
144 // Treat as untyped. | 111 return JS('', '#', String); |
145 return JS('', '#', jsobject); | 112 case "symbol": |
113 default: | |
114 return JS('', '#', jsobject); | |
146 } | 115 } |
147 if (result == null) { | |
148 return JS('', '#', jsobject); | |
149 } | |
150 return result; | |
151 } | 116 } |
152 | 117 |
153 /// Given an internal runtime type object, wraps it in a `WrappedType` object | 118 /// Given an internal runtime type object, wraps it in a `WrappedType` object |
154 /// that implements the dart:core Type interface. | 119 /// that implements the dart:core Type interface. |
155 Type wrapType(type) { | 120 Type wrapType(type) { |
156 // If we've already wrapped this type once, use the previous wrapper. This | 121 // If we've already wrapped this type once, use the previous wrapper. This |
157 // way, multiple references to the same type return an identical Type. | 122 // way, multiple references to the same type return an identical Type. |
158 if (JS('bool', '#.hasOwnProperty(#)', type, _typeObject)) { | 123 if (JS('bool', '#.hasOwnProperty(#)', type, _typeObject)) { |
159 return JS('', '#[#]', type, _typeObject); | 124 return JS('', '#[#]', type, _typeObject); |
160 } | 125 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
200 if (module == null) return null; | 165 if (module == null) return null; |
201 JS('', '#[#] = #', module, _moduleName, name); | 166 JS('', '#[#] = #', module, _moduleName, name); |
202 return module; | 167 return module; |
203 } | 168 } |
204 | 169 |
205 /// Track all libraries | 170 /// Track all libraries |
206 void trackLibraries(String moduleName, libraries, sourceMap) { | 171 void trackLibraries(String moduleName, libraries, sourceMap) { |
207 JS('', '#.set(#, #)', _loadedSourceMaps, moduleName, sourceMap); | 172 JS('', '#.set(#, #)', _loadedSourceMaps, moduleName, sourceMap); |
208 JS('', '#.set(#, #)', _loadedModules, moduleName, libraries); | 173 JS('', '#.set(#, #)', _loadedModules, moduleName, libraries); |
209 } | 174 } |
OLD | NEW |