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 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 402 JS('', 'dartx[#] = #', name, sym); | 402 JS('', 'dartx[#] = #', name, sym); |
| 403 } | 403 } |
| 404 return sym; | 404 return sym; |
| 405 } | 405 } |
| 406 | 406 |
| 407 defineExtensionNames(names) => | 407 defineExtensionNames(names) => |
| 408 JS('', '#.forEach(#)', names, getExtensionSymbol); | 408 JS('', '#.forEach(#)', names, getExtensionSymbol); |
| 409 | 409 |
| 410 /// Install properties in prototype-first order. Properties / descriptors from | 410 /// Install properties in prototype-first order. Properties / descriptors from |
| 411 /// more specific types should overwrite ones from less specific types. | 411 /// more specific types should overwrite ones from less specific types. |
| 412 void _installProperties(jsProto, extProto) { | 412 void _installProperties(jsProto, dartType, installedParent) { |
| 413 // This relies on the Dart type literal evaluating to the JavaScript | 413 if (JS('bool', '# === #', dartType, Object)) { |
| 414 // constructor. | 414 _installPropertiesForObject(jsProto); |
| 415 var coreObjProto = JS('', '#.prototype', Object); | 415 return; |
| 416 } | |
| 417 var dartProto = JS('', '#.prototype', dartType); | |
| 418 if (JS('bool', '# === #', jsProto, dartProto)) return; | |
|
vsm
2017/06/30 18:08:47
This was there before, but I'm not sure I understa
Jennifer Messerly
2017/07/05 21:17:16
Yeah, I'm not sure! It might've been a guard again
| |
| 416 | 419 |
| 417 var parentsExtension = JS('', '(#.__proto__)[#]', jsProto, _extensionType); | 420 // If the extension methods of the parent have been installed on the parent |
| 418 var installedParent = | 421 // of [jsProto], the methods will be available via prototype inheritance. |
| 419 JS('', '# && #.prototype', parentsExtension, parentsExtension); | 422 var dartSupertype = JS('', '#.__proto__', dartType); |
| 423 if (JS('bool', '# !== #', dartSupertype, installedParent)) { | |
| 424 _installProperties(jsProto, dartSupertype, installedParent); | |
| 425 } | |
| 420 | 426 |
| 421 _installProperties2(jsProto, extProto, coreObjProto, installedParent); | 427 copyTheseProperties(jsProto, dartProto, getOwnPropertySymbols(dartProto)); |
| 422 } | 428 } |
| 423 | 429 |
| 424 void _installProperties2(jsProto, extProto, coreObjProto, installedParent) { | 430 void _installPropertiesForObject(jsProto) { |
| 425 if (JS('bool', '# === #', extProto, coreObjProto)) { | |
| 426 _installPropertiesForObject(jsProto, coreObjProto); | |
| 427 return; | |
| 428 } | |
| 429 if (JS('bool', '# !== #', jsProto, extProto)) { | |
| 430 var extParent = JS('', '#.__proto__', extProto); | |
| 431 | |
| 432 // If the extension methods of the parent have been installed on the parent | |
| 433 // of [jsProto], the methods will be available via prototype inheritance. | |
| 434 | |
| 435 if (JS('bool', '# !== #', installedParent, extParent)) { | |
| 436 _installProperties2(jsProto, extParent, coreObjProto, installedParent); | |
| 437 } | |
| 438 } | |
| 439 copyTheseProperties(jsProto, extProto, getOwnPropertySymbols(extProto)); | |
| 440 } | |
| 441 | |
| 442 void _installPropertiesForObject(jsProto, coreObjProto) { | |
| 443 // core.Object members need to be copied from the non-symbol name to the | 431 // core.Object members need to be copied from the non-symbol name to the |
| 444 // symbol name. | 432 // symbol name. |
| 433 var coreObjProto = JS('', '#.prototype', Object); | |
| 445 var names = getOwnPropertyNames(coreObjProto); | 434 var names = getOwnPropertyNames(coreObjProto); |
| 446 for (int i = 0; i < JS('int', '#.length', names); ++i) { | 435 for (int i = 0; i < JS('int', '#.length', names); ++i) { |
| 447 var name = JS('', '#[#]', names, i); | 436 var name = JS('', '#[#]', names, i); |
| 448 var desc = getOwnPropertyDescriptor(coreObjProto, name); | 437 var desc = getOwnPropertyDescriptor(coreObjProto, name); |
| 449 defineProperty(jsProto, getExtensionSymbol(name), desc); | 438 defineProperty(jsProto, getExtensionSymbol(name), desc); |
| 450 } | 439 } |
| 451 return; | |
| 452 } | 440 } |
| 453 | 441 |
| 454 /// Copy symbols from the prototype of the source to destination. | 442 /// Copy symbols from the prototype of the source to destination. |
| 455 /// These are the only properties safe to copy onto an existing public | 443 /// These are the only properties safe to copy onto an existing public |
| 456 /// JavaScript class. | 444 /// JavaScript class. |
| 457 registerExtension(jsType, dartExtType) => JS( | 445 registerExtension(jsType, dartExtType) => JS( |
| 458 '', | 446 '', |
| 459 '''(() => { | 447 '''(() => { |
| 460 // TODO(vsm): Not all registered js types are real. | 448 // TODO(vsm): Not all registered js types are real. |
| 461 if (!jsType) return; | 449 if (!jsType) return; |
| 462 | 450 |
| 463 let extProto = $dartExtType.prototype; | |
| 464 let jsProto = $jsType.prototype; | 451 let jsProto = $jsType.prototype; |
| 465 | 452 |
| 466 // TODO(vsm): This sometimes doesn't exist on FF. These types will be | 453 // TODO(vsm): This sometimes doesn't exist on FF. These types will be |
| 467 // broken. | 454 // broken. |
| 468 if (!jsProto) return; | 455 if (!jsProto) return; |
| 469 | 456 |
| 457 $_installProperties(jsProto, $dartExtType, jsProto[$_extensionType]); | |
| 458 | |
| 470 // Mark the JS type's instances so we can easily check for extensions. | 459 // Mark the JS type's instances so we can easily check for extensions. |
| 471 jsProto[$_extensionType] = $dartExtType; | 460 jsProto[$_extensionType] = $dartExtType; |
| 472 $_installProperties(jsProto, extProto); | 461 |
| 473 function updateSig(sigF) { | 462 function updateSig(sigF) { |
| 474 let originalDesc = $getOwnPropertyDescriptor($dartExtType, sigF); | 463 let originalDesc = $getOwnPropertyDescriptor($dartExtType, sigF); |
| 475 if (originalDesc === void 0) return; | 464 if (originalDesc === void 0) return; |
| 476 let originalSigFn = originalDesc.get; | 465 let originalSigFn = originalDesc.get; |
| 477 $assert_(originalSigFn); | 466 $assert_(originalSigFn); |
| 478 $defineMemoizedGetter($jsType, sigF, originalSigFn); | 467 $defineMemoizedGetter($jsType, sigF, originalSigFn); |
| 479 } | 468 } |
| 480 updateSig($_methodSig); | 469 updateSig($_methodSig); |
| 481 updateSig($_fieldSig); | 470 updateSig($_fieldSig); |
| 482 updateSig($_getterSig); | 471 updateSig($_getterSig); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 539 })()'''); | 528 })()'''); |
| 540 | 529 |
| 541 /// Sets the type of `obj` to be `type` | 530 /// Sets the type of `obj` to be `type` |
| 542 setType(obj, type) { | 531 setType(obj, type) { |
| 543 JS('', '#.__proto__ = #.prototype', obj, type); | 532 JS('', '#.__proto__ = #.prototype', obj, type); |
| 544 return obj; | 533 return obj; |
| 545 } | 534 } |
| 546 | 535 |
| 547 /// Sets the element type of a list literal. | 536 /// Sets the element type of a list literal. |
| 548 list(obj, elementType) => | 537 list(obj, elementType) => |
| 549 JS('', '$setType($obj, ${getGenericClass(JSArray)}($elementType))'); | 538 setType(obj, JS('', '#(#)', getGenericClass(JSArray), elementType)); |
| 550 | 539 |
| 551 /// Link the extension to the type it's extending as a base class. | 540 /// Link the extension to the type it's extending as a base class. |
| 552 setBaseClass(derived, base) { | 541 setBaseClass(derived, base) { |
| 553 JS('', '#.prototype.__proto__ = #.prototype', derived, base); | 542 JS('', '#.prototype.__proto__ = #.prototype', derived, base); |
| 554 // We use __proto__ to track the superclass hierarchy (see isSubtype). | 543 // We use __proto__ to track the superclass hierarchy (see isSubtype). |
| 555 JS('', '#.__proto__ = #', derived, base); | 544 JS('', '#.__proto__ = #', derived, base); |
| 556 } | 545 } |
| 557 | 546 |
| 558 /// Like [setBaseClass] but for generic extension types, e.g. `JSArray<E>` | 547 /// Like [setBaseClass], but for generic extension types such as `JSArray<E>`. |
| 559 setExtensionBaseClass(derived, base) { | 548 setExtensionBaseClass(dartType, jsType) { |
| 560 // Mark the generic type as an extension type and link the prototype objects | 549 // Mark the generic type as an extension type and link the prototype objects. |
| 561 return JS( | 550 var dartProto = JS('', '#.prototype', dartType); |
| 562 '', | 551 JS('', '#[#] = #', dartProto, _extensionType, dartType); |
| 563 '''(() => { | 552 JS('', '#.__proto__ = #.prototype', dartProto, jsType); |
| 564 if ($base) { | |
| 565 $derived.prototype[$_extensionType] = $derived; | |
| 566 $derived.prototype.__proto__ = $base.prototype | |
| 567 } | |
| 568 })()'''); | |
| 569 } | 553 } |
| 570 | 554 |
| 571 defineEnumValues(enumClass, names) { | 555 defineEnumValues(enumClass, names) { |
| 572 var values = []; | 556 var values = []; |
| 573 for (var i = 0; i < JS('int', '#.length', names); i++) { | 557 for (var i = 0; i < JS('int', '#.length', names); i++) { |
| 574 var value = const_(JS('', 'new #.new(#)', enumClass, i)); | 558 var value = const_(JS('', 'new #.new(#)', enumClass, i)); |
| 575 JS('', '#.push(#)', values, value); | 559 JS('', '#.push(#)', values, value); |
| 576 defineValue(enumClass, JS('', '#[#]', names, i), value); | 560 defineValue(enumClass, JS('', '#[#]', names, i), value); |
| 577 } | 561 } |
| 578 JS('', '#.values = #', enumClass, constList(values, enumClass)); | 562 JS('', '#.values = #', enumClass, constList(values, enumClass)); |
| 579 } | 563 } |
| OLD | NEW |