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 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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 46 | 46 |
| 47 // Set the signature of the Mixin class to be the composition | 47 // Set the signature of the Mixin class to be the composition |
| 48 // of the signatures of the mixins. | 48 // of the signatures of the mixins. |
| 49 $setSignature(Mixin, { | 49 $setSignature(Mixin, { |
| 50 methods: () => { | 50 methods: () => { |
| 51 let s = {}; | 51 let s = {}; |
| 52 for (let m of $mixins) { | 52 for (let m of $mixins) { |
| 53 $copyProperties(s, m[$_methodSig]); | 53 $copyProperties(s, m[$_methodSig]); |
| 54 } | 54 } |
| 55 return s; | 55 return s; |
| 56 }, | |
| 57 fields: () => { | |
|
Jacob
2017/01/21 01:11:30
hole in propagating metadata
| |
| 58 let s = {}; | |
| 59 for (let m of $mixins) { | |
| 60 $copyProperties(s, m[$_fieldSig]); | |
| 61 } | |
| 62 return s; | |
| 63 }, | |
| 64 getters: () => { | |
| 65 let s = {}; | |
| 66 for (let m of $mixins) { | |
| 67 $copyProperties(s, m[$_getterSig]); | |
| 68 } | |
| 69 return s; | |
| 70 }, | |
| 71 setters: () => { | |
| 72 let s = {}; | |
| 73 for (let m of $mixins) { | |
| 74 $copyProperties(s, m[$_setterSig]); | |
| 75 } | |
| 76 return s; | |
| 56 } | 77 } |
| 57 }); | 78 }); |
| 58 | 79 |
| 59 // Save mixins for reflection | 80 // Save mixins for reflection |
| 60 Mixin[$_mixins] = $mixins; | 81 Mixin[$_mixins] = $mixins; |
| 61 return Mixin; | 82 return Mixin; |
| 62 })()'''); | 83 })()'''); |
| 63 | 84 |
| 64 /// The Symbol for storing type arguments on a specialized generic type. | 85 /// The Symbol for storing type arguments on a specialized generic type. |
| 65 final _mixins = JS('', 'Symbol("mixins")'); | 86 final _mixins = JS('', 'Symbol("mixins")'); |
| 66 | 87 |
| 67 getMixins(clazz) => JS('', 'Object.hasOwnProperty.call(#, #) ? #[#] : null', cla zz, _mixins, clazz, _mixins); | 88 getMixins(clazz) => JS('', 'Object.hasOwnProperty.call(#, #) ? #[#] : null', |
| 89 clazz, _mixins, clazz, _mixins); | |
| 68 | 90 |
| 69 @JSExportName('implements') | 91 @JSExportName('implements') |
| 70 final _implements = JS('', 'Symbol("implements")'); | 92 final _implements = JS('', 'Symbol("implements")'); |
| 71 | 93 |
| 72 getImplements(clazz) => JS('', 'Object.hasOwnProperty.call(#, #) ? #[#] : null', clazz, _implements, clazz, _implements); | 94 getImplements(clazz) => JS('', 'Object.hasOwnProperty.call(#, #) ? #[#] : null', |
| 95 clazz, _implements, clazz, _implements); | |
| 73 | 96 |
| 74 /// The Symbol for storing type arguments on a specialized generic type. | 97 /// The Symbol for storing type arguments on a specialized generic type. |
| 75 final _typeArguments = JS('', 'Symbol("typeArguments")'); | 98 final _typeArguments = JS('', 'Symbol("typeArguments")'); |
| 76 | 99 |
| 77 final _originalDeclaration = JS('', 'Symbol("originalDeclaration")'); | 100 final _originalDeclaration = JS('', 'Symbol("originalDeclaration")'); |
| 78 | 101 |
| 79 /// Wrap a generic class builder function with future flattening. | 102 /// Wrap a generic class builder function with future flattening. |
| 80 flattenFutures(builder) => JS( | 103 flattenFutures(builder) => JS( |
| 81 '', | 104 '', |
| 82 '''(() => { | 105 '''(() => { |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 144 | 167 |
| 145 getGenericClass(type) => | 168 getGenericClass(type) => |
| 146 JS('', '$safeGetOwnProperty($type, $_originalDeclaration)'); | 169 JS('', '$safeGetOwnProperty($type, $_originalDeclaration)'); |
| 147 | 170 |
| 148 getGenericArgs(type) => JS('', '$safeGetOwnProperty($type, $_typeArguments)'); | 171 getGenericArgs(type) => JS('', '$safeGetOwnProperty($type, $_typeArguments)'); |
| 149 | 172 |
| 150 // TODO(vsm): Collapse into one expando. | 173 // TODO(vsm): Collapse into one expando. |
| 151 final _constructorSig = JS('', 'Symbol("sigCtor")'); | 174 final _constructorSig = JS('', 'Symbol("sigCtor")'); |
| 152 final _methodSig = JS('', 'Symbol("sigMethod")'); | 175 final _methodSig = JS('', 'Symbol("sigMethod")'); |
| 153 final _fieldSig = JS('', 'Symbol("sigField")'); | 176 final _fieldSig = JS('', 'Symbol("sigField")'); |
| 154 final _getterSig= JS('', 'Symbol("sigGetter")'); | 177 final _getterSig = JS('', 'Symbol("sigGetter")'); |
| 155 final _setterSig= JS('', 'Symbol("sigSetter")'); | 178 final _setterSig = JS('', 'Symbol("sigSetter")'); |
| 156 final _staticSig = JS('', 'Symbol("sigStaticMethod")'); | 179 final _staticSig = JS('', 'Symbol("sigStaticMethod")'); |
| 157 final _staticFieldSig = JS('', 'Symbol("sigStaticField")'); | 180 final _staticFieldSig = JS('', 'Symbol("sigStaticField")'); |
| 158 final _staticGetterSig= JS('', 'Symbol("sigStaticGetter")'); | 181 final _staticGetterSig = JS('', 'Symbol("sigStaticGetter")'); |
|
Jacob
2017/01/21 01:11:30
Ran the formatter. Sorry about the formatter relat
| |
| 159 final _staticSetterSig= JS('', 'Symbol("sigStaticSetter")'); | 182 final _staticSetterSig = JS('', 'Symbol("sigStaticSetter")'); |
| 160 final _genericTypeCtor = JS('', 'Symbol("genericType")'); | 183 final _genericTypeCtor = JS('', 'Symbol("genericType")'); |
| 161 | 184 |
| 162 // TODO(vsm): Collapse this as well - just provide a dart map to mirrors code. | 185 // TODO(vsm): Collapse this as well - just provide a dart map to mirrors code. |
| 163 // These are queried by mirrors code. | 186 // These are queried by mirrors code. |
| 164 getConstructorSig(value) => JS('', '#[#]', value, _constructorSig); | 187 getConstructorSig(value) => JS('', '#[#]', value, _constructorSig); |
| 165 getMethodSig(value) => JS('', '#[#]', value, _methodSig); | 188 getMethodSig(value) => JS('', '#[#]', value, _methodSig); |
| 166 getFieldSig(value) => JS('', '#[#]', value, _fieldSig); | 189 getFieldSig(value) => JS('', '#[#]', value, _fieldSig); |
| 167 getGetterSig(value) => JS('', '#[#]', value, _getterSig); | 190 getGetterSig(value) => JS('', '#[#]', value, _getterSig); |
| 168 getSetterSig(value) => JS('', '#[#]', value, _setterSig); | 191 getSetterSig(value) => JS('', '#[#]', value, _setterSig); |
| 169 getStaticSig(value) => JS('', '#[#]', value, _staticSig); | 192 getStaticSig(value) => JS('', '#[#]', value, _staticSig); |
| 170 getStaticFieldSig(value) => JS('', '#[#]', value, _staticFieldSig); | 193 getStaticFieldSig(value) => JS('', '#[#]', value, _staticFieldSig); |
| 171 getStaticGetterSig(value) => JS('', '#[#]', value, _staticGetterSig); | 194 getStaticGetterSig(value) => JS('', '#[#]', value, _staticGetterSig); |
| 172 getStaticSetterSig(value) => JS('', '#[#]', value, _staticSetterSig); | 195 getStaticSetterSig(value) => JS('', '#[#]', value, _staticSetterSig); |
| 173 | 196 |
| 174 getGenericTypeCtor(value) => JS('', '#[#]', value, _genericTypeCtor); | 197 getGenericTypeCtor(value) => JS('', '#[#]', value, _genericTypeCtor); |
| 175 | 198 |
| 176 /// 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 |
| 177 getMethodType(obj, name) => JS( | 200 getType(obj) => JS( |
| 178 '', | 201 '', |
| 179 '''(() => { | 202 '''(() => { |
| 180 let type = $obj == null ? $Object : $obj.__proto__.constructor; | 203 return $obj == null ? $Object : $obj.__proto__.constructor; |
| 181 return $getMethodTypeFromType(type, $name); | |
| 182 })()'''); | 204 })()'''); |
| 183 | 205 |
| 184 /// Get the type of a method from a type using the stored signature | 206 /// Get the type of a method from a type using the stored signature |
| 185 getMethodTypeFromType(type, name) => JS( | 207 getMethodType(type, name) => JS( |
|
Jacob
2017/01/21 01:11:30
removed the getMethodType call that used an object
| |
| 186 '', | 208 '', |
| 187 '''(() => { | 209 '''(() => { |
| 188 let sigObj = $type[$_methodSig]; | 210 let sigObj = $type[$_methodSig]; |
| 189 if (sigObj === void 0) return void 0; | 211 if (sigObj === void 0) return void 0; |
| 190 return sigObj[$name]; | 212 return sigObj[$name]; |
| 191 })()'''); | 213 })()'''); |
| 192 | 214 |
| 215 getFieldType(type, name) => JS( | |
| 216 '', | |
| 217 '''(() => { | |
| 218 let sigObj = $type[$_fieldSig]; | |
| 219 if (sigObj === void 0) return void 0; | |
| 220 return sigObj[$name]; | |
| 221 })()'''); | |
| 222 | |
| 223 getSetterType(type, name) => JS( | |
| 224 '', | |
| 225 '''(() => { | |
| 226 let sigObj = $type[$_setterSig]; | |
| 227 if (sigObj === void 0) return void 0; | |
| 228 return sigObj[$name]; | |
| 229 })()'''); | |
| 230 | |
| 193 /// Get the type of a constructor from a class using the stored signature | 231 /// Get the type of a constructor from a class using the stored signature |
| 194 /// If name is undefined, returns the type of the default constructor | 232 /// If name is undefined, returns the type of the default constructor |
| 195 /// Returns undefined if the constructor is not found. | 233 /// Returns undefined if the constructor is not found. |
| 196 classGetConstructorType(cls, name) => JS( | 234 classGetConstructorType(cls, name) => JS( |
| 197 '', | 235 '', |
| 198 '''(() => { | 236 '''(() => { |
| 199 if(!$name) $name = 'new'; | 237 if(!$name) $name = 'new'; |
| 200 if ($cls === void 0) return void 0; | 238 if ($cls === void 0) return void 0; |
| 201 if ($cls == null) return void 0; | 239 if ($cls == null) return void 0; |
| 202 let sigCtor = $cls[$_constructorSig]; | 240 let sigCtor = $cls[$_constructorSig]; |
| 203 if (sigCtor === void 0) return void 0; | 241 if (sigCtor === void 0) return void 0; |
| 204 return sigCtor[$name]; | 242 return sigCtor[$name]; |
| 205 })()'''); | 243 })()'''); |
| 206 | 244 |
| 207 /// Given an object and a method name, tear off the method. | 245 /// Given an object and a method name, tear off the method. |
| 208 /// Sets the runtime type of the torn off method appropriately, | 246 /// Sets the runtime type of the torn off method appropriately, |
| 209 /// and also binds the object. | 247 /// and also binds the object. |
| 210 /// | 248 /// |
| 211 /// If the optional `f` argument is passed in, it will be used as the method. | 249 /// If the optional `f` argument is passed in, it will be used as the method. |
| 212 /// This supports cases like `super.foo` where we need to tear off the method | 250 /// This supports cases like `super.foo` where we need to tear off the method |
| 213 /// from the superclass, not from the `obj` directly. | 251 /// from the superclass, not from the `obj` directly. |
| 214 /// TODO(leafp): Consider caching the tearoff on the object? | 252 /// TODO(leafp): Consider caching the tearoff on the object? |
| 215 bind(obj, name, f) => JS( | 253 bind(obj, name, f) => JS( |
| 216 '', | 254 '', |
| 217 '''(() => { | 255 '''(() => { |
| 218 if ($f === void 0) $f = $obj[$name]; | 256 if ($f === void 0) $f = $obj[$name]; |
| 219 $f = $f.bind($obj); | 257 $f = $f.bind($obj); |
| 220 // TODO(jmesserly): track the function's signature on the function, instead | 258 // TODO(jmesserly): track the function's signature on the function, instead |
| 221 // of having to go back to the class? | 259 // of having to go back to the class? |
| 222 let sig = $getMethodType($obj, $name); | 260 let sig = $getMethodType($getType($obj), $name); |
| 223 $assert_(sig); | 261 $assert_(sig); |
| 224 $tag($f, sig); | 262 $tag($f, sig); |
| 225 return $f; | 263 return $f; |
| 226 })()'''); | 264 })()'''); |
| 227 | 265 |
| 228 /// Instantiate a generic method. | 266 /// Instantiate a generic method. |
| 229 /// | 267 /// |
| 230 /// We need to apply the type arguments both to the function, as well as its | 268 /// We need to apply the type arguments both to the function, as well as its |
| 231 /// associated function type. | 269 /// associated function type. |
| 232 gbind(f, @rest typeArgs) { | 270 gbind(f, @rest typeArgs) { |
| 233 var result = JS('', '#.apply(null, #)', f, typeArgs); | 271 var result = JS('', '#.apply(null, #)', f, typeArgs); |
| 234 var sig = JS('', '#.apply(null, #)', _getRuntimeType(f), typeArgs); | 272 var sig = JS('', '#.apply(null, #)', _getRuntimeType(f), typeArgs); |
| 235 tag(result, sig); | 273 tag(result, sig); |
| 236 return result; | 274 return result; |
| 237 } | 275 } |
| 238 | 276 |
| 239 // Set up the method signature field on the constructor | 277 // Set up the method signature field on the constructor |
| 240 _setInstanceSignature(f, sigF, kind) => JS( | 278 _setInstanceSignature(f, sigF, kind) => JS( |
| 241 '', | 279 '', |
| 242 '''(() => { | 280 '''(() => { |
| 243 $defineMemoizedGetter($f, $kind, () => { | 281 $defineMemoizedGetter($f, $kind, () => { |
| 244 let sigObj = $sigF(); | 282 let sigObj = $sigF(); |
| 245 sigObj.__proto__ = $f.__proto__[$kind]; | 283 let proto = $f.__proto__; |
| 284 // We need to set the root proto to null not undefined. | |
|
Jacob
2017/01/21 01:11:30
This bug resulted in our type metadata looking lik
| |
| 285 sigObj.__proto__ = ($kind in proto) ? proto[$kind] : null; | |
| 246 return sigObj; | 286 return sigObj; |
| 247 }); | 287 }); |
| 248 })()'''); | 288 })()'''); |
| 249 | 289 |
| 250 _setMethodSignature(f, sigF) => _setInstanceSignature(f, sigF, _methodSig); | 290 _setMethodSignature(f, sigF) => _setInstanceSignature(f, sigF, _methodSig); |
| 251 _setFieldSignature(f, sigF) => _setInstanceSignature(f, sigF, _fieldSig); | 291 _setFieldSignature(f, sigF) => _setInstanceSignature(f, sigF, _fieldSig); |
| 252 _setGetterSignature(f, sigF) => _setInstanceSignature(f, sigF, _getterSig); | 292 _setGetterSignature(f, sigF) => _setInstanceSignature(f, sigF, _getterSig); |
| 253 _setSetterSignature(f, sigF) => _setInstanceSignature(f, sigF, _setterSig); | 293 _setSetterSignature(f, sigF) => _setInstanceSignature(f, sigF, _setterSig); |
| 254 | 294 |
| 255 // Set up the constructor signature field on the constructor | 295 // Set up the constructor signature field on the constructor |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 323 $_setFieldSignature($f, fields); | 363 $_setFieldSignature($f, fields); |
| 324 $_setGetterSignature($f, getters); | 364 $_setGetterSignature($f, getters); |
| 325 $_setSetterSignature($f, setters); | 365 $_setSetterSignature($f, setters); |
| 326 $_setStaticSignature($f, statics); | 366 $_setStaticSignature($f, statics); |
| 327 $_setStaticFieldSignature($f, staticFields); | 367 $_setStaticFieldSignature($f, staticFields); |
| 328 $_setStaticGetterSignature($f, staticGetters); | 368 $_setStaticGetterSignature($f, staticGetters); |
| 329 $_setStaticSetterSignature($f, staticSetters); | 369 $_setStaticSetterSignature($f, staticSetters); |
| 330 $_setStaticTypes($f, names); | 370 $_setStaticTypes($f, names); |
| 331 })()'''); | 371 })()'''); |
| 332 | 372 |
| 333 hasMethod(obj, name) => JS('', '$getMethodType($obj, $name) !== void 0'); | 373 _hasSigEntry(type, sigF, name) => JS( |
| 374 '', | |
| 375 '''(() => { | |
| 376 let sigObj = $type[$sigF]; | |
| 377 if (sigObj === void 0) return false; | |
| 378 return $name in sigObj; | |
| 379 })()'''); | |
| 380 | |
| 381 hasMethod(type, name) => _hasSigEntry(type, _methodSig, name); | |
| 382 hasGetter(type, name) => _hasSigEntry(type, _getterSig, name); | |
| 383 hasSetter(type, name) => _hasSigEntry(type, _setterSig, name); | |
| 384 hasField(type, name) => _hasSigEntry(type, _fieldSig, name); | |
| 334 | 385 |
| 335 /// Given a class and an initializer method name, creates a constructor | 386 /// Given a class and an initializer method name, creates a constructor |
| 336 /// function with the same name. | 387 /// function with the same name. |
| 337 /// | 388 /// |
| 338 /// After we define the named constructor, the class can be constructed with | 389 /// After we define the named constructor, the class can be constructed with |
| 339 /// `new SomeClass.name(args)`. | 390 /// `new SomeClass.name(args)`. |
| 340 defineNamedConstructor(clazz, name) => JS( | 391 defineNamedConstructor(clazz, name) => JS( |
| 341 '', | 392 '', |
| 342 '''(() => { | 393 '''(() => { |
| 343 let proto = $clazz.prototype; | 394 let proto = $clazz.prototype; |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 424 let extProto = $dartExtType.prototype; | 475 let extProto = $dartExtType.prototype; |
| 425 let jsProto = $jsType.prototype; | 476 let jsProto = $jsType.prototype; |
| 426 | 477 |
| 427 // TODO(vsm): This sometimes doesn't exist on FF. These types will be | 478 // TODO(vsm): This sometimes doesn't exist on FF. These types will be |
| 428 // broken. | 479 // broken. |
| 429 if (!jsProto) return; | 480 if (!jsProto) return; |
| 430 | 481 |
| 431 // Mark the JS type's instances so we can easily check for extensions. | 482 // Mark the JS type's instances so we can easily check for extensions. |
| 432 jsProto[$_extensionType] = $dartExtType; | 483 jsProto[$_extensionType] = $dartExtType; |
| 433 $_installProperties(jsProto, extProto); | 484 $_installProperties(jsProto, extProto); |
| 434 let originalSigFn = $getOwnPropertyDescriptor($dartExtType, $_methodSig).get; | 485 function updateSig(sigF) { |
|
Jacob
2017/01/21 01:11:30
We were forgetting to call updateSig on anything b
| |
| 435 $assert_(originalSigFn); | 486 let originalSigFn = $getOwnPropertyDescriptor($dartExtType, sigF).get; |
| 436 $defineMemoizedGetter($jsType, $_methodSig, originalSigFn); | 487 $assert_(originalSigFn); |
| 488 $defineMemoizedGetter($jsType, sigF, originalSigFn); | |
| 489 } | |
| 490 updateSig($_methodSig); | |
| 491 updateSig($_fieldSig); | |
| 492 updateSig($_getterSig); | |
| 493 updateSig($_setterSig); | |
| 437 })()'''); | 494 })()'''); |
| 438 | 495 |
| 439 /// | 496 /// |
| 440 /// Mark a concrete type as implementing extension methods. | 497 /// Mark a concrete type as implementing extension methods. |
| 441 /// For example: `class MyIter implements Iterable`. | 498 /// For example: `class MyIter implements Iterable`. |
| 442 /// | 499 /// |
| 443 /// This takes a list of names, which are the extension methods implemented. | 500 /// This takes a list of names, which are the extension methods implemented. |
| 444 /// It will add a forwarder, so the extension method name redirects to the | 501 /// It will add a forwarder, so the extension method name redirects to the |
| 445 /// normal Dart method name. For example: | 502 /// normal Dart method name. For example: |
| 446 /// | 503 /// |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 462 for (let name of $methodNames) { | 519 for (let name of $methodNames) { |
| 463 let method = $getOwnPropertyDescriptor(proto, name); | 520 let method = $getOwnPropertyDescriptor(proto, name); |
| 464 $defineProperty(proto, $getExtensionSymbol(name), method); | 521 $defineProperty(proto, $getExtensionSymbol(name), method); |
| 465 } | 522 } |
| 466 // Ensure the signature is available too. | 523 // Ensure the signature is available too. |
| 467 // TODO(jmesserly): not sure if we can do this in a cleaner way. Essentially | 524 // TODO(jmesserly): not sure if we can do this in a cleaner way. Essentially |
| 468 // we need to copy the signature (and in the future, other data like | 525 // we need to copy the signature (and in the future, other data like |
| 469 // annotations) any time we copy a method as part of our metaprogramming. | 526 // annotations) any time we copy a method as part of our metaprogramming. |
| 470 // It might be more friendly to JS metaprogramming if we include this info | 527 // It might be more friendly to JS metaprogramming if we include this info |
| 471 // on the function. | 528 // on the function. |
| 472 let originalSigFn = $getOwnPropertyDescriptor($type, $_methodSig).get; | 529 |
| 473 $defineMemoizedGetter(type, $_methodSig, function() { | 530 function upgradeSig(sigF) { |
| 474 let sig = originalSigFn(); | 531 let originalSigFn = $getOwnPropertyDescriptor($type, sigF).get; |
| 475 for (let name of $methodNames) { | 532 $defineMemoizedGetter(type, sigF, function() { |
| 476 sig[$getExtensionSymbol(name)] = sig[name]; | 533 let sig = originalSigFn(); |
| 477 } | 534 let propertyNames = Object.getOwnPropertyNames(sig); |
| 478 return sig; | 535 for (let name of methodNames) { |
| 479 }); | 536 if (name in sig) { |
| 537 sig[$getExtensionSymbol(name)] = sig[name]; | |
| 538 } | |
| 539 } | |
| 540 return sig; | |
| 541 }); | |
| 542 }; | |
| 543 upgradeSig($_methodSig); | |
| 544 upgradeSig($_fieldSig); | |
| 545 upgradeSig($_getterSig); | |
| 546 upgradeSig($_setterSig); | |
| 480 })()'''); | 547 })()'''); |
| 481 | 548 |
| 482 /// Sets the type of `obj` to be `type` | 549 /// Sets the type of `obj` to be `type` |
| 483 setType(obj, type) { | 550 setType(obj, type) { |
| 484 JS('', '#.__proto__ = #.prototype', obj, type); | 551 JS('', '#.__proto__ = #.prototype', obj, type); |
| 485 return obj; | 552 return obj; |
| 486 } | 553 } |
| 487 | 554 |
| 488 /// Sets the element type of a list literal. | 555 /// Sets the element type of a list literal. |
| 489 list(obj, elementType) => | 556 list(obj, elementType) => |
| 490 JS('', '$setType($obj, ${getGenericClass(JSArray)}($elementType))'); | 557 JS('', '$setType($obj, ${getGenericClass(JSArray)}($elementType))'); |
| 491 | 558 |
| 492 /// Link the extension to the type it's extending as a base class. | 559 /// Link the extension to the type it's extending as a base class. |
| 493 setBaseClass(derived, base) { | 560 setBaseClass(derived, base) { |
| 494 JS('', '#.prototype.__proto__ = #.prototype', derived, base); | 561 JS('', '#.prototype.__proto__ = #.prototype', derived, base); |
| 495 // We use __proto__ to track the superclass hierarchy (see isSubtype). | 562 // We use __proto__ to track the superclass hierarchy (see isSubtype). |
| 496 JS('', '#.__proto__ = #', derived, base); | 563 JS('', '#.__proto__ = #', derived, base); |
| 497 } | 564 } |
| 498 | 565 |
| 499 /// Like [setBaseClass] but for generic extension types, e.g. `JSArray<E>` | 566 /// Like [setBaseClass] but for generic extension types, e.g. `JSArray<E>` |
| 500 setExtensionBaseClass(derived, base) { | 567 setExtensionBaseClass(derived, base) { |
| 501 // Mark the generic type as an extension type and link the prototype objects | 568 // Mark the generic type as an extension type and link the prototype objects |
| 502 return JS('', '''(() => { | 569 return JS( |
| 570 '', | |
| 571 '''(() => { | |
| 503 if ($base) { | 572 if ($base) { |
| 504 $derived.prototype[$_extensionType] = $derived; | 573 $derived.prototype[$_extensionType] = $derived; |
| 505 $derived.prototype.__proto__ = $base.prototype | 574 $derived.prototype.__proto__ = $base.prototype |
| 506 } | 575 } |
| 507 })()'''); | 576 })()'''); |
| 508 } | 577 } |
| 509 | 578 |
| 510 /// Given a special constructor function that creates a function instances, | 579 /// Given a special constructor function that creates a function instances, |
| 511 /// and a class with a `call` method, merge them so the constructor function | 580 /// and a class with a `call` method, merge them so the constructor function |
| 512 /// will have the correct methods and prototype. | 581 /// will have the correct methods and prototype. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 548 '''(() => { | 617 '''(() => { |
| 549 let values = []; | 618 let values = []; |
| 550 for (var i = 0; i < $names.length; i++) { | 619 for (var i = 0; i < $names.length; i++) { |
| 551 let value = $const_(new $enumClass(i)); | 620 let value = $const_(new $enumClass(i)); |
| 552 values.push(value); | 621 values.push(value); |
| 553 Object.defineProperty($enumClass, $names[i], | 622 Object.defineProperty($enumClass, $names[i], |
| 554 { value: value, configurable: true }); | 623 { value: value, configurable: true }); |
| 555 } | 624 } |
| 556 $enumClass.values = $constList(values, $enumClass); | 625 $enumClass.values = $constList(values, $enumClass); |
| 557 })()'''); | 626 })()'''); |
| OLD | NEW |