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 operations that define and manipulate Dart | 5 /// This library defines the operations that define and manipulate Dart |
6 /// classes. Included in this are: | 6 /// classes. Included in this are: |
7 /// - Generics | 7 /// - Generics |
8 /// - Class metadata | 8 /// - Class metadata |
9 /// - Extension methods | 9 /// - Extension methods |
10 /// | 10 /// |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 getGetterSig(value) => JS('', '#[#]', value, _getterSig); | 190 getGetterSig(value) => JS('', '#[#]', value, _getterSig); |
191 getSetterSig(value) => JS('', '#[#]', value, _setterSig); | 191 getSetterSig(value) => JS('', '#[#]', value, _setterSig); |
192 getStaticSig(value) => JS('', '#[#]', value, _staticSig); | 192 getStaticSig(value) => JS('', '#[#]', value, _staticSig); |
193 getStaticFieldSig(value) => JS('', '#[#]', value, _staticFieldSig); | 193 getStaticFieldSig(value) => JS('', '#[#]', value, _staticFieldSig); |
194 getStaticGetterSig(value) => JS('', '#[#]', value, _staticGetterSig); | 194 getStaticGetterSig(value) => JS('', '#[#]', value, _staticGetterSig); |
195 getStaticSetterSig(value) => JS('', '#[#]', value, _staticSetterSig); | 195 getStaticSetterSig(value) => JS('', '#[#]', value, _staticSetterSig); |
196 | 196 |
197 getGenericTypeCtor(value) => JS('', '#[#]', value, _genericTypeCtor); | 197 getGenericTypeCtor(value) => JS('', '#[#]', value, _genericTypeCtor); |
198 | 198 |
199 /// Get the type of a method from an object using the stored signature | 199 /// Get the type of a method from an object using the stored signature |
200 getType(obj) => JS( | 200 getType(obj) => |
201 '', | 201 JS('', '# == null ? # : #.__proto__.constructor', obj, Object, obj); |
202 '''(() => { | |
203 return $obj == null ? $Object : $obj.__proto__.constructor; | |
204 })()'''); | |
205 | 202 |
206 bool isJsInterop(obj) { | 203 bool isJsInterop(obj) { |
207 if (JS('bool', 'typeof # === "function"', obj)) { | 204 if (JS('bool', 'typeof # === "function"', obj)) { |
208 // A function is a Dart function if it has runtime type information. | 205 // A function is a Dart function if it has runtime type information. |
209 return _getRuntimeType(obj) == null; | 206 return _getRuntimeType(obj) == null; |
210 } | 207 } |
211 // Primitive types are not JS interop types. | 208 // Primitive types are not JS interop types. |
212 if (JS('bool', 'typeof # !== "object"', obj)) return false; | 209 if (JS('bool', 'typeof # !== "object"', obj)) return false; |
213 | 210 |
214 // Extension types are not considered JS interop types. | 211 // Extension types are not considered JS interop types. |
215 // Note that it is still possible to call typed JS interop methods on | 212 // Note that it is still possible to call typed JS interop methods on |
216 // extension types but the calls must be statically typed. | 213 // extension types but the calls must be statically typed. |
217 if (getExtensionType(obj) != null) return false; | 214 if (getExtensionType(obj) != null) return false; |
218 return JS('bool', '!($obj instanceof $Object)'); | 215 return JS('bool', '!($obj instanceof $Object)'); |
219 } | 216 } |
220 | 217 |
221 /// Get the type of a method from a type using the stored signature | 218 /// Get the type of a method from a type using the stored signature |
222 getMethodType(type, name) => JS( | 219 getMethodType(type, name) { |
223 '', | 220 var m = JS('', '#[#]', type, _methodSig); |
224 '''(() => { | 221 return m != null ? JS('', '#[#]', m, name) : null; |
225 let sigObj = $type[$_methodSig]; | 222 } |
226 if (sigObj === void 0) return void 0; | |
227 return sigObj[$name]; | |
228 })()'''); | |
229 | 223 |
230 getFieldType(type, name) => JS( | 224 /// Gets the type of the corresponding setter (this includes writable fields). |
231 '', | 225 getSetterType(type, name) { |
232 '''(() => { | 226 var signature = JS('', '#[#]', type, _setterSig); |
233 let sigObj = $type[$_fieldSig]; | 227 if (signature != null) { |
234 if (sigObj === void 0) return void 0; | 228 var type = JS('', '#[#]', signature, name); |
235 let fieldType = sigObj[$name]; | 229 if (type != null) { |
236 // workaround to handle metadata. | 230 // TODO(jmesserly): it would be nice not to encode setters with a full |
237 return (fieldType instanceof Array) ? fieldType[0] : fieldType; | 231 // function type. |
238 })()'''); | 232 return JS('', '#.args[0]', type); |
| 233 } |
| 234 } |
| 235 signature = JS('', '#[#]', type, _fieldSig); |
| 236 if (signature != null) { |
| 237 var fieldInfo = JS('', '#[#]', signature, name); |
| 238 if (fieldInfo != null && JS('bool', '!#.isFinal', fieldInfo)) { |
| 239 return JS('', '#.type', fieldInfo); |
| 240 } |
| 241 } |
| 242 return null; |
| 243 } |
239 | 244 |
240 getSetterType(type, name) => JS( | 245 finalFieldType(type, metadata) => |
241 '', | 246 JS('', '{ type: #, isFinal: true, metadata: # }', type, metadata); |
242 '''(() => { | 247 |
243 let sigObj = $type[$_setterSig]; | 248 fieldType(type, metadata) => |
244 if (sigObj === void 0) return void 0; | 249 JS('', '{ type: #, isFinal: false, metadata: # }', type, metadata); |
245 return sigObj[$name]; | |
246 })()'''); | |
247 | 250 |
248 /// Get the type of a constructor from a class using the stored signature | 251 /// Get the type of a constructor from a class using the stored signature |
249 /// If name is undefined, returns the type of the default constructor | 252 /// If name is undefined, returns the type of the default constructor |
250 /// Returns undefined if the constructor is not found. | 253 /// Returns undefined if the constructor is not found. |
251 classGetConstructorType(cls, name) => JS( | 254 classGetConstructorType(cls, name) => JS( |
252 '', | 255 '', |
253 '''(() => { | 256 '''(() => { |
254 if(!$name) $name = 'new'; | 257 if(!$name) $name = 'new'; |
255 if ($cls === void 0) return void 0; | 258 if ($cls === void 0) return void 0; |
256 if ($cls == null) return void 0; | 259 if ($cls == null) return void 0; |
(...skipping 14 matching lines...) Expand all Loading... |
271 '', | 274 '', |
272 '''(() => { | 275 '''(() => { |
273 if ($f === void 0) $f = $obj[$name]; | 276 if ($f === void 0) $f = $obj[$name]; |
274 // TODO(jmesserly): track the function's signature on the function, instead | 277 // TODO(jmesserly): track the function's signature on the function, instead |
275 // of having to go back to the class? | 278 // of having to go back to the class? |
276 let sig = $getMethodType($getType($obj), $name); | 279 let sig = $getMethodType($getType($obj), $name); |
277 | 280 |
278 // JS interop case: do not bind this for compatibility with the dart2js | 281 // JS interop case: do not bind this for compatibility with the dart2js |
279 // implementation where we cannot bind this reliably here until we trust | 282 // implementation where we cannot bind this reliably here until we trust |
280 // types more. | 283 // types more. |
281 if (sig === void 0) return $f; | 284 if (sig == null) return $f; |
282 | 285 |
283 $f = $f.bind($obj); | 286 $f = $f.bind($obj); |
284 $tag($f, sig); | 287 $tag($f, sig); |
285 return $f; | 288 return $f; |
286 })()'''); | 289 })()'''); |
287 | 290 |
288 /// Instantiate a generic method. | 291 /// Instantiate a generic method. |
289 /// | 292 /// |
290 /// We need to apply the type arguments both to the function, as well as its | 293 /// We need to apply the type arguments both to the function, as well as its |
291 /// associated function type. | 294 /// associated function type. |
292 gbind(f, @rest typeArgs) { | 295 gbind(f, @rest typeArgs) { |
293 var result = JS('', '#.apply(null, #)', f, typeArgs); | 296 var result = JS('', '#.apply(null, #)', f, typeArgs); |
294 var sig = JS('', '#.instantiate(#)', _getRuntimeType(f), typeArgs); | 297 var sig = JS('', '#.instantiate(#)', _getRuntimeType(f), typeArgs); |
295 tag(result, sig); | 298 tag(result, sig); |
296 return result; | 299 return result; |
297 } | 300 } |
298 | 301 |
299 // Set up the method signature field on the constructor | 302 // Set up the method signature field on the constructor |
300 _setInstanceSignature(f, sigF, kind) => JS( | 303 _setInstanceSignature(f, sigF, kind) => defineMemoizedGetter( |
301 '', | 304 f, |
302 '''(() => { | 305 kind, |
303 $defineMemoizedGetter($f, $kind, () => { | 306 JS( |
304 let sigObj = $sigF(); | 307 '', |
305 let proto = $f.__proto__; | 308 '''() => { |
306 // We need to set the root proto to null not undefined. | 309 let sigObj = #(); |
307 sigObj.__proto__ = ($kind in proto) ? proto[$kind] : null; | 310 let proto = #.__proto__; |
308 return sigObj; | 311 // We need to set the root proto to null not undefined. |
309 }); | 312 sigObj.__proto__ = (# in proto) ? proto[#] : null; |
310 })()'''); | 313 return sigObj; |
| 314 }''', |
| 315 sigF, |
| 316 f, |
| 317 kind, |
| 318 kind)); |
311 | 319 |
312 _setMethodSignature(f, sigF) => _setInstanceSignature(f, sigF, _methodSig); | 320 _setMethodSignature(f, sigF) => _setInstanceSignature(f, sigF, _methodSig); |
313 _setFieldSignature(f, sigF) => _setInstanceSignature(f, sigF, _fieldSig); | 321 _setFieldSignature(f, sigF) => _setInstanceSignature(f, sigF, _fieldSig); |
314 _setGetterSignature(f, sigF) => _setInstanceSignature(f, sigF, _getterSig); | 322 _setGetterSignature(f, sigF) => _setInstanceSignature(f, sigF, _getterSig); |
315 _setSetterSignature(f, sigF) => _setInstanceSignature(f, sigF, _setterSig); | 323 _setSetterSignature(f, sigF) => _setInstanceSignature(f, sigF, _setterSig); |
316 | 324 |
317 // Set up the constructor signature field on the constructor | 325 // Set up the constructor signature field on the constructor |
318 _setConstructorSignature(f, sigF) => | 326 _setConstructorSignature(f, sigF) => |
319 JS('', '$defineMemoizedGetter($f, $_constructorSig, $sigF)'); | 327 JS('', '$defineMemoizedGetter($f, $_constructorSig, $sigF)'); |
320 | 328 |
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
643 '''(() => { | 651 '''(() => { |
644 let values = []; | 652 let values = []; |
645 for (var i = 0; i < $names.length; i++) { | 653 for (var i = 0; i < $names.length; i++) { |
646 let value = $const_(new $enumClass(i)); | 654 let value = $const_(new $enumClass(i)); |
647 values.push(value); | 655 values.push(value); |
648 Object.defineProperty($enumClass, $names[i], | 656 Object.defineProperty($enumClass, $names[i], |
649 { value: value, configurable: true }); | 657 { value: value, configurable: true }); |
650 } | 658 } |
651 $enumClass.values = $constList(values, $enumClass); | 659 $enumClass.values = $constList(values, $enumClass); |
652 })()'''); | 660 })()'''); |
OLD | NEW |