OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 part of js_backend; | 5 part of js_backend; |
6 | 6 |
7 /** | 7 /** |
8 * A function element that represents a closure call. The signature is copied | 8 * A function element that represents a closure call. The signature is copied |
9 * from the given element. | 9 * from the given element. |
10 */ | 10 */ |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
229 // constructor. | 229 // constructor. |
230 // For engines where we have access to the '__proto__' we can manipulate | 230 // For engines where we have access to the '__proto__' we can manipulate |
231 // the object literal directly. For other engines we have to create a new | 231 // the object literal directly. For other engines we have to create a new |
232 // object and copy over the members. | 232 // object and copy over the members. |
233 return ''' | 233 return ''' |
234 function(collectedClasses) { | 234 function(collectedClasses) { |
235 var hasOwnProperty = Object.prototype.hasOwnProperty; | 235 var hasOwnProperty = Object.prototype.hasOwnProperty; |
236 for (var cls in collectedClasses) { | 236 for (var cls in collectedClasses) { |
237 if (hasOwnProperty.call(collectedClasses, cls)) { | 237 if (hasOwnProperty.call(collectedClasses, cls)) { |
238 var desc = collectedClasses[cls]; | 238 var desc = collectedClasses[cls]; |
239 $isolatePropertiesName[cls] = $defineClassName(cls, desc[''], desc); | 239 '''/* The second argument of defineNativeClass is the list of fields, |
ahe
2012/11/22 13:51:52
defineNativeClass?!?
ngeoffray
2012/11/22 13:54:17
:-), changed to defineClassName.
| |
240 which might be undefined if there is no field. */''' | |
floitsch
2012/11/22 13:59:30
If the class doesn't have any declared fields (in
ngeoffray
2012/11/22 14:01:41
Done.
| |
241 $isolatePropertiesName[cls] = $defineClassName(cls, desc[''] || [], desc); | |
240 if (desc['super'] !== "") $pendingClassesName[cls] = desc['super']; | 242 if (desc['super'] !== "") $pendingClassesName[cls] = desc['super']; |
241 } | 243 } |
242 } | 244 } |
243 var pendingClasses = $pendingClassesName; | 245 var pendingClasses = $pendingClassesName; |
244 '''/* FinishClasses can be called multiple times. This means that we need to | 246 '''/* FinishClasses can be called multiple times. This means that we need to |
245 clear the pendingClasses property. */''' | 247 clear the pendingClasses property. */''' |
246 $pendingClassesName = {}; | 248 $pendingClassesName = {}; |
247 var finishedClasses = {}; | 249 var finishedClasses = {}; |
248 function finishClass(cls) { | 250 function finishClass(cls) { |
249 '''/* Opera does not support 'getOwnPropertyNames'. Therefore we use | 251 '''/* Opera does not support 'getOwnPropertyNames'. Therefore we use |
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
670 emitExtraAccessors(member, defineInstanceMember); | 672 emitExtraAccessors(member, defineInstanceMember); |
671 } | 673 } |
672 | 674 |
673 /** | 675 /** |
674 * Documentation wanted -- johnniwinther | 676 * Documentation wanted -- johnniwinther |
675 * | 677 * |
676 * Invariant: [classElement] must be a declaration element. | 678 * Invariant: [classElement] must be a declaration element. |
677 */ | 679 */ |
678 void emitInstanceMembers(ClassElement classElement, | 680 void emitInstanceMembers(ClassElement classElement, |
679 CodeBuffer buffer, | 681 CodeBuffer buffer, |
680 bool needsLeadingComma) { | 682 bool emitLeadingComma) { |
681 assert(invariant(classElement, classElement.isDeclaration)); | 683 assert(invariant(classElement, classElement.isDeclaration)); |
682 bool needsComma = needsLeadingComma; | |
683 void defineInstanceMember(String name, StringBuffer memberBuffer) { | 684 void defineInstanceMember(String name, StringBuffer memberBuffer) { |
684 if (needsComma) buffer.add(','); | 685 if (emitLeadingComma) buffer.add(','); |
685 needsComma = true; | 686 emitLeadingComma = true; |
686 buffer.add('\n'); | 687 buffer.add('\n'); |
687 buffer.add(' $name: '); | 688 buffer.add(' $name: '); |
688 buffer.add(memberBuffer); | 689 buffer.add(memberBuffer); |
689 } | 690 } |
690 | 691 |
691 JavaScriptBackend backend = compiler.backend; | 692 JavaScriptBackend backend = compiler.backend; |
692 if (classElement == backend.objectInterceptorClass) { | 693 if (classElement == backend.objectInterceptorClass) { |
693 emitInterceptorMethods(defineInstanceMember); | 694 emitInterceptorMethods(defineInstanceMember); |
694 // The ObjectInterceptor does not have any instance methods. | 695 // The ObjectInterceptor does not have any instance methods. |
695 return; | 696 return; |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
845 String setterName = | 846 String setterName = |
846 namer.publicSetterName(new SourceString(accessorName)); | 847 namer.publicSetterName(new SourceString(accessorName)); |
847 buffer.add("$setterName: function(v) { " | 848 buffer.add("$setterName: function(v) { " |
848 "this.$fieldName = $helperName(v$additionalArgument); }"); | 849 "this.$fieldName = $helperName(v$additionalArgument); }"); |
849 } | 850 } |
850 | 851 |
851 void emitClassConstructor(ClassElement classElement, CodeBuffer buffer) { | 852 void emitClassConstructor(ClassElement classElement, CodeBuffer buffer) { |
852 /* Do nothing. */ | 853 /* Do nothing. */ |
853 } | 854 } |
854 | 855 |
855 void emitClassFields(ClassElement classElement, CodeBuffer buffer) { | 856 void emitClassFields(ClassElement classElement, |
856 buffer.add('"": ['); | 857 CodeBuffer buffer, |
858 bool emitEndingComma) { | |
857 bool isFirstField = true; | 859 bool isFirstField = true; |
858 visitClassFields(classElement, (Element member, | 860 visitClassFields(classElement, (Element member, |
859 String name, | 861 String name, |
860 String accessorName, | 862 String accessorName, |
861 bool needsGetter, | 863 bool needsGetter, |
862 bool needsSetter, | 864 bool needsSetter, |
863 bool needsCheckedSetter) { | 865 bool needsCheckedSetter) { |
864 if (isFirstField) { | 866 if (isFirstField) { |
867 buffer.add('"": ['); | |
865 isFirstField = false; | 868 isFirstField = false; |
866 } else { | 869 } else { |
867 buffer.add(", "); | 870 buffer.add(", "); |
868 } | 871 } |
869 buffer.add('"$accessorName'); | 872 buffer.add('"$accessorName'); |
870 int flag = 0; | 873 int flag = 0; |
871 if (name != accessorName) { | 874 if (name != accessorName) { |
872 buffer.add(':$name'); | 875 buffer.add(':$name'); |
873 assert(needsGetter || needsSetter); | 876 assert(needsGetter || needsSetter); |
874 flag = RENAMING_FLAG; | 877 flag = RENAMING_FLAG; |
875 } | 878 } |
876 if (needsGetter && needsSetter) { | 879 if (needsGetter && needsSetter) { |
877 buffer.addCharCode(GETTER_SETTER_CODE + flag); | 880 buffer.addCharCode(GETTER_SETTER_CODE + flag); |
878 } else if (needsGetter) { | 881 } else if (needsGetter) { |
879 buffer.addCharCode(GETTER_CODE + flag); | 882 buffer.addCharCode(GETTER_CODE + flag); |
880 } else if (needsSetter) { | 883 } else if (needsSetter) { |
881 buffer.addCharCode(SETTER_CODE + flag); | 884 buffer.addCharCode(SETTER_CODE + flag); |
882 } | 885 } |
883 buffer.add('"'); | 886 buffer.add('"'); |
884 }); | 887 }); |
885 buffer.add(']'); | 888 if (!isFirstField) { |
889 // There was at least one field. | |
890 buffer.add(']'); | |
891 if (emitEndingComma) { | |
892 buffer.add(', '); | |
893 } | |
894 } | |
886 } | 895 } |
887 | 896 |
888 /** Each getter/setter must be prefixed with a ",\n ". */ | 897 /** Each getter/setter must be prefixed with a ",\n ". */ |
889 void emitClassGettersSetters(ClassElement classElement, CodeBuffer buffer, | 898 void emitClassGettersSetters(ClassElement classElement, |
890 {bool omitLeadingComma: false}) { | 899 CodeBuffer buffer, |
900 bool emitLeadingComma) { | |
891 visitClassFields(classElement, (Element member, | 901 visitClassFields(classElement, (Element member, |
892 String name, | 902 String name, |
893 String accessorName, | 903 String accessorName, |
894 bool needsGetter, | 904 bool needsGetter, |
895 bool needsSetter, | 905 bool needsSetter, |
896 bool needsCheckedSetter) { | 906 bool needsCheckedSetter) { |
897 if (needsCheckedSetter) { | 907 if (needsCheckedSetter) { |
898 assert(!needsSetter); | 908 assert(!needsSetter); |
899 if (!omitLeadingComma) { | 909 if (emitLeadingComma) { |
900 buffer.add(",\n "); | 910 buffer.add(",\n "); |
901 } else { | 911 } else { |
902 omitLeadingComma = false; | 912 emitLeadingComma = true; |
903 } | 913 } |
904 generateCheckedSetter(member, name, accessorName, buffer); | 914 generateCheckedSetter(member, name, accessorName, buffer); |
905 } | 915 } |
906 }); | 916 }); |
907 } | 917 } |
908 | 918 |
909 /** | 919 /** |
910 * Documentation wanted -- johnniwinther | 920 * Documentation wanted -- johnniwinther |
911 * | 921 * |
912 * Invariant: [classElement] must be a declaration element. | 922 * Invariant: [classElement] must be a declaration element. |
(...skipping 12 matching lines...) Expand all Loading... | |
925 | 935 |
926 needsDefineClass = true; | 936 needsDefineClass = true; |
927 String className = namer.getName(classElement); | 937 String className = namer.getName(classElement); |
928 ClassElement superclass = classElement.superclass; | 938 ClassElement superclass = classElement.superclass; |
929 String superName = ""; | 939 String superName = ""; |
930 if (superclass != null) { | 940 if (superclass != null) { |
931 superName = namer.getName(superclass); | 941 superName = namer.getName(superclass); |
932 } | 942 } |
933 | 943 |
934 buffer.add('$classesCollector.$className = {'); | 944 buffer.add('$classesCollector.$className = {'); |
935 emitClassConstructor(classElement, buffer); | 945 emitClassConstructor(classElement, buffer, true); |
936 emitClassFields(classElement, buffer); | 946 emitClassFields(classElement, buffer, true); |
937 // TODO(floitsch): the emitInstanceMember should simply always emit a ',\n'. | 947 // TODO(floitsch): the emitInstanceMember should simply always emit a ',\n'. |
938 // That does currently not work because the native classes have a different | 948 // That does currently not work because the native classes have a different |
939 // syntax. | 949 // syntax. |
940 buffer.add(',\n "super": "$superName"'); | 950 buffer.add('\n "super": "$superName"'); |
941 emitClassGettersSetters(classElement, buffer); | 951 emitClassGettersSetters(classElement, buffer, true); |
942 emitInstanceMembers(classElement, buffer, true); | 952 emitInstanceMembers(classElement, buffer); |
943 buffer.add('\n};\n\n'); | 953 buffer.add('\n};\n\n'); |
944 } | 954 } |
945 | 955 |
946 void emitInterceptorMethods( | 956 void emitInterceptorMethods( |
947 void defineInstanceMember(String name, StringBuffer memberBuffer)) { | 957 void defineInstanceMember(String name, StringBuffer memberBuffer)) { |
948 JavaScriptBackend backend = compiler.backend; | 958 JavaScriptBackend backend = compiler.backend; |
949 // Emit forwarders for the ObjectInterceptor class. We need to | 959 // Emit forwarders for the ObjectInterceptor class. We need to |
950 // emit all possible sends on intercepted methods. | 960 // emit all possible sends on intercepted methods. |
951 for (Selector selector in backend.usedInterceptors) { | 961 for (Selector selector in backend.usedInterceptors) { |
952 String name; | 962 String name; |
(...skipping 792 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1745 const String HOOKS_API_USAGE = """ | 1755 const String HOOKS_API_USAGE = """ |
1746 // Generated by dart2js, the Dart to JavaScript compiler. | 1756 // Generated by dart2js, the Dart to JavaScript compiler. |
1747 // The code supports the following hooks: | 1757 // The code supports the following hooks: |
1748 // dartPrint(message) - if this function is defined it is called | 1758 // dartPrint(message) - if this function is defined it is called |
1749 // instead of the Dart [print] method. | 1759 // instead of the Dart [print] method. |
1750 // dartMainRunner(main) - if this function is defined, the Dart [main] | 1760 // dartMainRunner(main) - if this function is defined, the Dart [main] |
1751 // method will not be invoked directly. | 1761 // method will not be invoked directly. |
1752 // Instead, a closure that will invoke [main] is | 1762 // Instead, a closure that will invoke [main] is |
1753 // passed to [dartMainRunner]. | 1763 // passed to [dartMainRunner]. |
1754 """; | 1764 """; |
OLD | NEW |