| 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 717 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 728 void emitInstanceMembers(ClassElement classElement, | 728 void emitInstanceMembers(ClassElement classElement, |
| 729 ClassBuilder builder) { | 729 ClassBuilder builder) { |
| 730 assert(invariant(classElement, classElement.isDeclaration)); | 730 assert(invariant(classElement, classElement.isDeclaration)); |
| 731 JavaScriptBackend backend = compiler.backend; | 731 JavaScriptBackend backend = compiler.backend; |
| 732 if (classElement == backend.objectInterceptorClass) { | 732 if (classElement == backend.objectInterceptorClass) { |
| 733 emitInterceptorMethods(builder); | 733 emitInterceptorMethods(builder); |
| 734 // The ObjectInterceptor does not have any instance methods. | 734 // The ObjectInterceptor does not have any instance methods. |
| 735 return; | 735 return; |
| 736 } | 736 } |
| 737 | 737 |
| 738 void visitMember(ClassElement enclosing, Element member) { |
| 739 assert(invariant(classElement, member.isDeclaration)); |
| 740 if (member.isInstanceMember()) { |
| 741 addInstanceMember(member, builder); |
| 742 } |
| 743 } |
| 744 |
| 745 // TODO(kasperl): We should make sure to only emit one version of |
| 746 // overridden methods. Right now, we rely on the ordering so the |
| 747 // methods pulled in from mixins are replaced with the members |
| 748 // from the class definition, but it is broken if you a chain of |
| 749 // mixin applications. |
| 750 |
| 751 // If the class is a native class, we have to add the instance |
| 752 // members defined in the non-native mixin applications used by |
| 753 // the class. |
| 754 if (classElement.isNative()) { |
| 755 ClassElement superclass = classElement.superclass; |
| 756 while (superclass.isMixinApplication) { |
| 757 assert(!superclass.isNative()); |
| 758 superclass.forEachMember( |
| 759 visitMember, |
| 760 includeBackendMembers: true, |
| 761 includeSuperMembers: false); |
| 762 superclass = superclass.superclass; |
| 763 } |
| 764 } |
| 765 |
| 738 classElement.implementation.forEachMember( | 766 classElement.implementation.forEachMember( |
| 739 (ClassElement enclosing, Element member) { | 767 visitMember, |
| 740 assert(invariant(classElement, member.isDeclaration)); | 768 includeBackendMembers: true, |
| 741 if (member.isInstanceMember()) { | 769 includeSuperMembers: false); |
| 742 addInstanceMember(member, builder); | |
| 743 } | |
| 744 }, | |
| 745 includeBackendMembers: true); | |
| 746 | 770 |
| 747 generateIsTestsOn(classElement, (Element other) { | 771 generateIsTestsOn(classElement, (Element other) { |
| 748 js.Expression code; | 772 js.Expression code; |
| 749 if (compiler.objectClass == other) return; | 773 if (compiler.objectClass == other) return; |
| 750 if (nativeEmitter.requiresNativeIsCheck(other)) { | 774 if (nativeEmitter.requiresNativeIsCheck(other)) { |
| 751 code = js.fun([], js.block1(js.return_(new js.LiteralBool(true)))); | 775 code = js.fun([], js.block1(js.return_(new js.LiteralBool(true)))); |
| 752 } else { | 776 } else { |
| 753 code = new js.LiteralBool(true); | 777 code = new js.LiteralBool(true); |
| 754 } | 778 } |
| 755 builder.addProperty(namer.operatorIs(other), code); | 779 builder.addProperty(namer.operatorIs(other), code); |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 884 // Getters and setters with suffixes will be generated dynamically. | 908 // Getters and setters with suffixes will be generated dynamically. |
| 885 addField(member, | 909 addField(member, |
| 886 fieldName, | 910 fieldName, |
| 887 accessorName, | 911 accessorName, |
| 888 needsGetter, | 912 needsGetter, |
| 889 needsSetter, | 913 needsSetter, |
| 890 needsCheckedSetter); | 914 needsCheckedSetter); |
| 891 } | 915 } |
| 892 } | 916 } |
| 893 | 917 |
| 918 // TODO(kasperl): We should make sure to only emit one version of |
| 919 // overridden fields. Right now, we rely on the ordering so the |
| 920 // fields pulled in from mixins are replaced with the fields from |
| 921 // the class definition, but it is broken if you a chain of mixin |
| 922 // applications. |
| 923 |
| 924 // If the class is a native class, we have to add the fields |
| 925 // defined in the non-native mixin applications used by the class. |
| 926 if (classElement.isNative()) { |
| 927 ClassElement superclass = classElement.superclass; |
| 928 while (superclass.isMixinApplication) { |
| 929 assert(!superclass.isNative()); |
| 930 superclass.forEachInstanceField( |
| 931 visitField, |
| 932 includeBackendMembers: true, |
| 933 includeSuperMembers: false); |
| 934 superclass = superclass.superclass; |
| 935 } |
| 936 } |
| 937 |
| 894 // If a class is not instantiated then we add the field just so we can | 938 // If a class is not instantiated then we add the field just so we can |
| 895 // generate the field getter/setter dynamically. Since this is only | 939 // generate the field getter/setter dynamically. Since this is only |
| 896 // allowed on fields that are in [classElement] we don't need to visit | 940 // allowed on fields that are in [classElement] we don't need to visit |
| 897 // superclasses for non-instantiated classes. | 941 // superclasses for non-instantiated classes. |
| 898 classElement.implementation.forEachInstanceField( | 942 classElement.implementation.forEachInstanceField( |
| 899 visitField, | 943 visitField, |
| 900 includeBackendMembers: true, | 944 includeBackendMembers: true, |
| 901 includeSuperMembers: isInstantiated && !classElement.isNative()); | 945 includeSuperMembers: isInstantiated && !classElement.isNative()); |
| 902 } | 946 } |
| 903 | 947 |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1061 return; | 1105 return; |
| 1062 } else { | 1106 } else { |
| 1063 // TODO(ngeoffray): Instead of switching between buffer, we | 1107 // TODO(ngeoffray): Instead of switching between buffer, we |
| 1064 // should create code sections, and decide where to emit them at | 1108 // should create code sections, and decide where to emit them at |
| 1065 // the end. | 1109 // the end. |
| 1066 buffer = mainBuffer; | 1110 buffer = mainBuffer; |
| 1067 } | 1111 } |
| 1068 | 1112 |
| 1069 needsDefineClass = true; | 1113 needsDefineClass = true; |
| 1070 String className = namer.getName(classElement); | 1114 String className = namer.getName(classElement); |
| 1115 |
| 1116 // Find the first non-native superclass. |
| 1071 ClassElement superclass = classElement.superclass; | 1117 ClassElement superclass = classElement.superclass; |
| 1118 while (superclass != null && superclass.isNative()) { |
| 1119 superclass = superclass.superclass; |
| 1120 } |
| 1121 |
| 1072 String superName = ""; | 1122 String superName = ""; |
| 1073 if (superclass != null) { | 1123 if (superclass != null) { |
| 1074 superName = namer.getName(superclass); | 1124 superName = namer.getName(superclass); |
| 1075 } | 1125 } |
| 1076 | 1126 |
| 1077 ClassBuilder builder = new ClassBuilder(); | 1127 ClassBuilder builder = new ClassBuilder(); |
| 1078 | 1128 |
| 1079 emitClassConstructor(classElement, builder); | 1129 emitClassConstructor(classElement, builder); |
| 1080 emitSuper(superName, builder); | 1130 emitSuper(superName, builder); |
| 1081 emitClassFields(classElement, builder, | 1131 emitClassFields(classElement, builder, |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1156 call = cls.lookupBackendMember(Compiler.CALL_OPERATOR_NAME); | 1206 call = cls.lookupBackendMember(Compiler.CALL_OPERATOR_NAME); |
| 1157 } | 1207 } |
| 1158 if (call != null) { | 1208 if (call != null) { |
| 1159 generateInterfacesIsTests(compiler.functionClass, | 1209 generateInterfacesIsTests(compiler.functionClass, |
| 1160 emitIsTest, | 1210 emitIsTest, |
| 1161 generated); | 1211 generated); |
| 1162 getTypedefChecksOn(call.computeType(compiler)).forEach(emitIsTest); | 1212 getTypedefChecksOn(call.computeType(compiler)).forEach(emitIsTest); |
| 1163 } | 1213 } |
| 1164 } | 1214 } |
| 1165 for (DartType interfaceType in cls.interfaces) { | 1215 for (DartType interfaceType in cls.interfaces) { |
| 1166 generateInterfacesIsTests(interfaceType.element, emitIsTest, generated); | 1216 ClassElement interfaceElement = interfaceType.element; |
| 1217 generateInterfacesIsTests(interfaceElement, emitIsTest, generated); |
| 1167 } | 1218 } |
| 1219 |
| 1220 // For native classes, we also have to run through their |
| 1221 // non-native mixin applications and make sure we deal with 'is' |
| 1222 // tests correctly for those. |
| 1223 if (cls.isNative()) { |
| 1224 ClassElement superclass = cls.superclass; |
| 1225 while (superclass != null && superclass.isMixinApplication) { |
| 1226 assert(!superclass.isNative()); |
| 1227 for (DartType interfaceType in superclass.interfaces) { |
| 1228 ClassElement interfaceElement = interfaceType.element; |
| 1229 generateInterfacesIsTests(interfaceElement, emitIsTest, generated); |
| 1230 } |
| 1231 superclass = superclass.superclass; |
| 1232 } |
| 1233 } |
| 1234 |
| 1168 } | 1235 } |
| 1169 | 1236 |
| 1170 /** | 1237 /** |
| 1171 * Generate "is tests" where [cls] is being implemented. | 1238 * Generate "is tests" where [cls] is being implemented. |
| 1172 */ | 1239 */ |
| 1173 void generateInterfacesIsTests(ClassElement cls, | 1240 void generateInterfacesIsTests(ClassElement cls, |
| 1174 void emitIsTest(ClassElement element), | 1241 void emitIsTest(ClassElement element), |
| 1175 Set<Element> alreadyGenerated) { | 1242 Set<Element> alreadyGenerated) { |
| 1176 void tryEmitTest(ClassElement cls) { | 1243 void tryEmitTest(ClassElement cls) { |
| 1177 if (!alreadyGenerated.contains(cls) && checkedClasses.contains(cls)) { | 1244 if (!alreadyGenerated.contains(cls) && checkedClasses.contains(cls)) { |
| (...skipping 1000 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2178 """; | 2245 """; |
| 2179 const String HOOKS_API_USAGE = """ | 2246 const String HOOKS_API_USAGE = """ |
| 2180 // The code supports the following hooks: | 2247 // The code supports the following hooks: |
| 2181 // dartPrint(message) - if this function is defined it is called | 2248 // dartPrint(message) - if this function is defined it is called |
| 2182 // instead of the Dart [print] method. | 2249 // instead of the Dart [print] method. |
| 2183 // dartMainRunner(main) - if this function is defined, the Dart [main] | 2250 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 2184 // method will not be invoked directly. | 2251 // method will not be invoked directly. |
| 2185 // Instead, a closure that will invoke [main] is | 2252 // Instead, a closure that will invoke [main] is |
| 2186 // passed to [dartMainRunner]. | 2253 // passed to [dartMainRunner]. |
| 2187 """; | 2254 """; |
| OLD | NEW |