| 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 |