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 var dart, _js_helper, _js_primitives, dartx; | 5 var dart, _js_helper, _js_primitives, dartx; |
| 6 (function (dart) { | 6 (function (dart) { |
| 7 'use strict'; | 7 'use strict'; |
| 8 | 8 |
| 9 // TODO(vsm): This is referenced (as init.globalState) from | 9 // TODO(vsm): This is referenced (as init.globalState) from |
| 10 // isolate_helper.dart. Where should it go? | 10 // isolate_helper.dart. Where should it go? |
| 11 // See: https://github.com/dart-lang/dev_compiler/issues/164 | 11 // See: https://github.com/dart-lang/dev_compiler/issues/164 |
| 12 dart.globalState = null; | 12 dart.globalState = null; |
| 13 | 13 |
| 14 const defineProperty = Object.defineProperty; | 14 const defineProperty = Object.defineProperty; |
| 15 const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; | 15 const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; |
| 16 const getOwnPropertyNames = Object.getOwnPropertyNames; | 16 const getOwnPropertyNames = Object.getOwnPropertyNames; |
| 17 const getOwnPropertySymbols = Object.getOwnPropertySymbols; | 17 const getOwnPropertySymbols = Object.getOwnPropertySymbols; |
| 18 const hasOwnProperty = Object.prototype.hasOwnProperty; | 18 const hasOwnProperty = Object.prototype.hasOwnProperty; |
| 19 const slice = [].slice; | 19 const slice = [].slice; |
| 20 | 20 |
| 21 let _constructorSig = Symbol('sigCtor'); | |
| 22 let _methodSig = Symbol("sig"); | |
| 23 let _staticSig = Symbol("sigStatic"); | |
| 24 | |
| 21 function getOwnNamesAndSymbols(obj) { | 25 function getOwnNamesAndSymbols(obj) { |
| 22 return getOwnPropertyNames(obj).concat(getOwnPropertySymbols(obj)); | 26 return getOwnPropertyNames(obj).concat(getOwnPropertySymbols(obj)); |
| 23 } | 27 } |
| 24 | 28 |
| 25 function dload(obj, field) { | 29 function dload(obj, field) { |
| 26 field = _canonicalFieldName(obj, field, [], field); | 30 field = _canonicalFieldName(obj, field, [], field); |
| 27 if (_getMethodType(obj, field) !== void 0) { | 31 if (_getMethodType(obj, field) !== void 0) { |
| 28 return dart.bind(obj, field); | 32 return dart.bind(obj, field); |
| 29 } | 33 } |
| 30 // TODO(vsm): Implement NSM robustly. An 'in' check breaks on certain | 34 // TODO(vsm): Implement NSM robustly. An 'in' check breaks on certain |
| (...skipping 716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 747 dart.defineLazyClassGeneric = defineLazyProperty; | 751 dart.defineLazyClassGeneric = defineLazyProperty; |
| 748 | 752 |
| 749 function defineMemoizedGetter(obj, name, get) { | 753 function defineMemoizedGetter(obj, name, get) { |
| 750 let cache = null; | 754 let cache = null; |
| 751 function getter() { | 755 function getter() { |
| 752 if (cache != null) return cache; | 756 if (cache != null) return cache; |
| 753 cache = get(); | 757 cache = get(); |
| 754 get = null; | 758 get = null; |
| 755 return cache; | 759 return cache; |
| 756 } | 760 } |
| 757 defineProperty(obj, name, {get : getter}); | 761 defineProperty(obj, name, {get: getter, configurable: true}); |
| 758 } | 762 } |
| 759 | 763 |
| 760 function copyPropertiesHelper(to, from, names) { | 764 function copyPropertiesHelper(to, from, names) { |
| 761 for (let name of names) { | 765 for (let name of names) { |
| 762 defineProperty(to, name, getOwnPropertyDescriptor(from, name)); | 766 defineProperty(to, name, getOwnPropertyDescriptor(from, name)); |
| 763 } | 767 } |
| 764 return to; | 768 return to; |
| 765 } | 769 } |
| 766 | 770 |
| 767 /** | 771 /** |
| 768 * Copy properties from source to destination object. | 772 * Copy properties from source to destination object. |
| 769 * This operation is commonly called `mixin` in JS. | 773 * This operation is commonly called `mixin` in JS. |
| 770 */ | 774 */ |
| 771 function copyProperties(to, from) { | 775 function copyProperties(to, from) { |
| 772 return copyPropertiesHelper(to, from, getOwnNamesAndSymbols(from)); | 776 return copyPropertiesHelper(to, from, getOwnNamesAndSymbols(from)); |
| 773 } | 777 } |
| 774 dart.copyProperties = copyProperties; | 778 dart.copyProperties = copyProperties; |
| 775 | 779 |
| 776 function getExtensionSymbol(name) { | 780 function extensionMember(name) { |
| 777 let sym = dartx[name]; | 781 let sym = dartx[name]; |
| 778 if (!sym) dartx[name] = sym = Symbol('dartx.' + name); | 782 if (!sym) dartx[name] = sym = Symbol('dartx.' + name); |
| 779 return sym; | 783 return sym; |
| 780 } | 784 } |
| 785 dart.extensionMember = extensionMember; | |
| 781 | 786 |
| 782 /** | 787 /** |
| 783 * Copy symbols from the prototype of the source to destination. | 788 * Copy symbols from the prototype of the source to destination. |
| 784 * These are the only properties safe to copy onto an existing public | 789 * These are the only properties safe to copy onto an existing public |
| 785 * JavaScript class. | 790 * JavaScript class. |
| 786 */ | 791 */ |
| 787 function registerExtension(jsType, dartExtType) { | 792 function registerExtension(jsType, dartExtType) { |
| 788 let extProto = dartExtType.prototype; | 793 let extProto = dartExtType.prototype; |
| 789 let jsProto = jsType.prototype; | 794 let jsProto = jsType.prototype; |
| 790 | 795 |
| 791 // Mark the JS type's instances so we can easily check for extensions. | 796 // Mark the JS type's instances so we can easily check for extensions. |
| 792 assert(jsProto[_extensionType] === void 0); | 797 assert(jsProto[_extensionType] === void 0); |
| 793 jsProto[_extensionType] = extProto; | 798 jsProto[_extensionType] = extProto; |
| 794 for (let name of getOwnPropertyNames(extProto)) { | 799 copyPropertiesHelper(jsProto, extProto, getOwnPropertySymbols(extProto)); |
| 795 let symbol = getExtensionSymbol(name); | |
| 796 defineProperty(jsProto, symbol, getOwnPropertyDescriptor(extProto, name)); | |
| 797 } | |
| 798 } | 800 } |
| 799 dart.registerExtension = registerExtension; | 801 dart.registerExtension = registerExtension; |
| 800 | 802 |
| 801 /** | 803 /** |
| 802 * Mark a concrete type as implementing extension methods. | 804 * Mark a concrete type as implementing extension methods. |
| 803 * For example: `class MyIter implements Iterable`. | 805 * For example: `class MyIter implements Iterable`. |
| 804 * | 806 * |
| 805 * This takes a list of names, which are the extension methods implemented. | 807 * This takes a list of names, which are the extension methods implemented. |
| 806 * It will add a forwarder, so the extension method name redirects to the | 808 * It will add a forwarder, so the extension method name redirects to the |
| 807 * normal Dart method name. For example: | 809 * normal Dart method name. For example: |
| 808 * | 810 * |
| 809 * defineExtensionMembers(MyType, ['add', 'remove']); | 811 * defineExtensionMembers(MyType, ['add', 'remove']); |
| 810 * | 812 * |
| 811 * Results in: | 813 * Results in: |
| 812 * | 814 * |
| 813 * MyType.prototype[dartx.add] = MyType.prototype.add; | 815 * MyType.prototype[dartx.add] = MyType.prototype.add; |
| 814 * MyType.prototype[dartx.remove] = MyType.prototype.remove; | 816 * MyType.prototype[dartx.remove] = MyType.prototype.remove; |
| 815 */ | 817 */ |
| 816 // TODO(jmesserly): essentially this gives two names to the same method. | 818 // TODO(jmesserly): essentially this gives two names to the same method. |
| 817 // This benefit is roughly equivalent call performance either way, but the | 819 // This benefit is roughly equivalent call performance either way, but the |
| 818 // cost is we need to call implementExtension any time a subclass overrides | 820 // cost is we need to call defineExtensionMEmbers any time a subclass override s |
| 819 // one of these methods. | 821 // one of these methods. |
| 820 function defineExtensionMembers(type, methodNames) { | 822 function defineExtensionMembers(type, methodNames) { |
| 821 let proto = type.prototype; | 823 let proto = type.prototype; |
| 822 for (let name of methodNames) { | 824 for (let name of methodNames) { |
| 823 let method = getOwnPropertyDescriptor(proto, name); | 825 let method = getOwnPropertyDescriptor(proto, name); |
| 824 defineProperty(proto, getExtensionSymbol(name), method); | 826 defineProperty(proto, extensionMember(name), method); |
| 825 } | 827 } |
| 828 // Ensure the signature is available too. | |
|
Leaf
2015/06/05 20:42:23
We could attach something to each method, but it s
Jennifer Messerly
2015/06/05 21:08:57
yeah, not sure in what sense it's wasteful, though
Jennifer Messerly
2015/06/05 21:10:34
also, wouldn't hypothetical Typed-ES likely work t
Leaf
2015/06/05 21:34:44
It's no big deal really. As it stands, we have a
| |
| 829 // TODO(jmesserly): can we make this cleaner? Ideally signatures would be | |
| 830 // associated with the methods, so copying the methods above would | |
| 831 // automatically copy the type signature too. | |
| 832 var originalSigFn = getOwnPropertyDescriptor(type, _methodSig).get; | |
| 833 defineMemoizedGetter(type, _methodSig, function() { | |
| 834 var sig = originalSigFn(); | |
| 835 for (let name of methodNames) { | |
| 836 sig[extensionMember(name)] = sig[name]; | |
| 837 } | |
| 838 return sig; | |
| 839 }); | |
| 826 } | 840 } |
| 827 dart.defineExtensionMembers = defineExtensionMembers; | 841 dart.defineExtensionMembers = defineExtensionMembers; |
| 828 | 842 |
| 829 function setBaseClass(derived, base) { | 843 function setBaseClass(derived, base) { |
| 830 // Link the extension to the type it's extending as a base class. | 844 // Link the extension to the type it's extending as a base class. |
| 831 derived.prototype.__proto__ = base.prototype; | 845 derived.prototype.__proto__ = base.prototype; |
| 832 } | 846 } |
| 833 dart.setBaseClass = setBaseClass; | 847 dart.setBaseClass = setBaseClass; |
| 834 | 848 |
| 835 /** | 849 /** |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 889 } | 903 } |
| 890 } | 904 } |
| 891 // Copy each mixin's methods, with later ones overwriting earlier entries. | 905 // Copy each mixin's methods, with later ones overwriting earlier entries. |
| 892 for (let m of mixins) { | 906 for (let m of mixins) { |
| 893 copyProperties(Mixin.prototype, m.prototype); | 907 copyProperties(Mixin.prototype, m.prototype); |
| 894 } | 908 } |
| 895 | 909 |
| 896 // Set the signature of the Mixin class to be the composition | 910 // Set the signature of the Mixin class to be the composition |
| 897 // of the signatures of the mixins. | 911 // of the signatures of the mixins. |
| 898 dart.setSignature(Mixin, { | 912 dart.setSignature(Mixin, { |
| 899 methods : () => { | 913 methods: () => { |
| 900 let s = {}; | 914 let s = {}; |
| 901 for (let m of mixins) { | 915 for (let m of mixins) { |
| 902 copyProperties(s, m[_methodSig]); | 916 copyProperties(s, m[_methodSig]); |
| 903 } | 917 } |
| 904 return s; | 918 return s; |
| 905 } | 919 } |
| 906 }); | 920 }); |
| 907 | 921 |
| 908 // Save mixins for reflection | 922 // Save mixins for reflection |
| 909 Mixin[dart.mixins] = mixins; | 923 Mixin[dart.mixins] = mixins; |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1013 } | 1027 } |
| 1014 map.set(arg, value); | 1028 map.set(arg, value); |
| 1015 } | 1029 } |
| 1016 } | 1030 } |
| 1017 return value; | 1031 return value; |
| 1018 } | 1032 } |
| 1019 return makeGenericType; | 1033 return makeGenericType; |
| 1020 } | 1034 } |
| 1021 dart.generic = generic; | 1035 dart.generic = generic; |
| 1022 | 1036 |
| 1023 let _constructorSig = Symbol('sigCtor'); | |
| 1024 let _methodSig = Symbol("sig"); | |
| 1025 let _staticSig = Symbol("sigStatic"); | |
| 1026 | |
| 1027 /// Get the type of a function using the store runtime type | 1037 /// Get the type of a function using the store runtime type |
| 1028 function _getFunctionType(f) { | 1038 function _getFunctionType(f) { |
| 1029 return f[_runtimeType]; | 1039 return f[_runtimeType]; |
| 1030 } | 1040 } |
| 1031 | 1041 |
| 1032 /// Get the type of a method using the stored signature | 1042 /// Get the type of a method using the stored signature |
| 1033 function _getMethodType(obj, name) { | 1043 function _getMethodType(obj, name) { |
| 1034 if (obj === void 0) return void 0; | 1044 if (obj === void 0) return void 0; |
| 1035 if (obj == null) return void 0; | 1045 if (obj == null) return void 0; |
| 1036 let sigObj = obj.__proto__.constructor[_methodSig]; | 1046 let sigObj = obj.__proto__.constructor[_methodSig]; |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1310 // TODO(vsm): DOM facades? | 1320 // TODO(vsm): DOM facades? |
| 1311 // See: https://github.com/dart-lang/dev_compiler/issues/173 | 1321 // See: https://github.com/dart-lang/dev_compiler/issues/173 |
| 1312 NodeList.prototype.get = function(i) { return this[i]; }; | 1322 NodeList.prototype.get = function(i) { return this[i]; }; |
| 1313 NamedNodeMap.prototype.get = function(i) { return this[i]; }; | 1323 NamedNodeMap.prototype.get = function(i) { return this[i]; }; |
| 1314 DOMTokenList.prototype.get = function(i) { return this[i]; }; | 1324 DOMTokenList.prototype.get = function(i) { return this[i]; }; |
| 1315 | 1325 |
| 1316 /** Dart extension members. */ | 1326 /** Dart extension members. */ |
| 1317 dartx = dartx || {}; | 1327 dartx = dartx || {}; |
| 1318 | 1328 |
| 1319 })(dart || (dart = {})); | 1329 })(dart || (dart = {})); |
| OLD | NEW |