Chromium Code Reviews| 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 |