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 |