Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(356)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart

Issue 11414255: dart2js: Dot-separated field-and-super descriptor string in class definitions. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 } 128 }
129 if (needsSetter) { 129 if (needsSetter) {
130 var setterString = "this." + field + " = v;"; 130 var setterString = "this." + field + " = v;";
131 prototype["set\$" + field] = new Function("v", setterString); 131 prototype["set\$" + field] = new Function("v", setterString);
132 } 132 }
133 return field; 133 return field;
134 }"""; 134 }""";
135 } 135 }
136 136
137 String get defineClassFunction { 137 String get defineClassFunction {
138 // First the class name, then the super class name, followed by the fields 138 // First the class name, then the field names in an array and the members
139 // (in an array) and the members (inside an Object literal). 139 // (inside an Object literal).
140 // The caller can also pass in the constructor as a function if needed. 140 // The caller can also pass in the constructor as a function if needed.
141 // 141 //
142 // Example: 142 // Example:
143 // defineClass("A", "B", ["x", "y"], { 143 // defineClass("A", ["x", "y"], {
karlklose 2012/11/30 11:43:34 Shouldn't this be defineClass("A":"B@x.y", { ?
erikcorry 2012/11/30 12:05:57 No, this is called from finishClassesFunction, whe
ngeoffray 2012/11/30 12:11:46 So where is B in defineClass now?
erikcorry 2012/11/30 12:20:02 We don't need the superclass here, so it's nowhere
144 // foo$1: function(y) { 144 // foo$1: function(y) {
145 // print(this.x + y); 145 // print(this.x + y);
146 // }, 146 // },
147 // bar$2: function(t, v) { 147 // bar$2: function(t, v) {
148 // this.x = t - v; 148 // this.x = t - v;
149 // }, 149 // },
150 // }); 150 // });
151 return """ 151 return """
152 function(cls, fields, prototype) { 152 function(cls, fields, prototype) {
153 var generateGetterSetter = $generateGetterSetterFunction; 153 var generateGetterSetter = $generateGetterSetterFunction;
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 // constructor. 207 // constructor.
208 // For engines where we have access to the '__proto__' we can manipulate 208 // For engines where we have access to the '__proto__' we can manipulate
209 // the object literal directly. For other engines we have to create a new 209 // the object literal directly. For other engines we have to create a new
210 // object and copy over the members. 210 // object and copy over the members.
211 return ''' 211 return '''
212 function(collectedClasses) { 212 function(collectedClasses) {
213 var hasOwnProperty = Object.prototype.hasOwnProperty; 213 var hasOwnProperty = Object.prototype.hasOwnProperty;
214 for (var cls in collectedClasses) { 214 for (var cls in collectedClasses) {
215 if (hasOwnProperty.call(collectedClasses, cls)) { 215 if (hasOwnProperty.call(collectedClasses, cls)) {
216 var desc = collectedClasses[cls]; 216 var desc = collectedClasses[cls];
217 '''/* If the class does not have any declared fields (in the '' 217 '''/* Get the superclass and the fields in the format Super@field1.field2 from
218 property of the description), then provide an empty list of fields. */''' 218 the null-string property on the descriptor. */'''
219 $isolatePropertiesName[cls] = $defineClassName(cls, desc[''] || [], desc); 219 var s = desc[''].split('@'), supr = s[0];
220 if (desc['super'] !== "") $pendingClassesName[cls] = desc['super']; 220 var fields = s[1] == '' ? [] : s[1].split('.');
221 $isolatePropertiesName[cls] = $defineClassName(cls, fields, desc);
222 if (supr) $pendingClassesName[cls] = supr;
221 } 223 }
222 } 224 }
223 var pendingClasses = $pendingClassesName; 225 var pendingClasses = $pendingClassesName;
224 '''/* FinishClasses can be called multiple times. This means that we need to 226 '''/* FinishClasses can be called multiple times. This means that we need to
225 clear the pendingClasses property. */''' 227 clear the pendingClasses property. */'''
226 $pendingClassesName = {}; 228 $pendingClassesName = {};
227 var finishedClasses = {}; 229 var finishedClasses = {};
228 function finishClass(cls) { 230 function finishClass(cls) {
229 '''/* Opera does not support 'getOwnPropertyNames'. Therefore we use 231 '''/* Opera does not support 'getOwnPropertyNames'. Therefore we use
230 hasOwnProperty instead. */''' 232 hasOwnProperty instead. */'''
(...skipping 10 matching lines...) Expand all
241 if ($supportsProtoName) { 243 if ($supportsProtoName) {
242 prototype.__proto__ = superConstructor.prototype; 244 prototype.__proto__ = superConstructor.prototype;
243 prototype.constructor = constructor; 245 prototype.constructor = constructor;
244 } else { 246 } else {
245 function tmp() {}; 247 function tmp() {};
246 tmp.prototype = superConstructor.prototype; 248 tmp.prototype = superConstructor.prototype;
247 var newPrototype = new tmp(); 249 var newPrototype = new tmp();
248 constructor.prototype = newPrototype; 250 constructor.prototype = newPrototype;
249 newPrototype.constructor = constructor; 251 newPrototype.constructor = constructor;
250 for (var member in prototype) { 252 for (var member in prototype) {
251 if (member == '' || member == 'super') continue; 253 if (!member) continue; '''/* if (member == '') */'''
ngeoffray 2012/11/30 12:11:46 What is this comment about?
erikcorry 2012/11/30 12:20:02 The comment shows the intent, the actual code does
252 if (hasOwnProperty.call(prototype, member)) { 254 if (hasOwnProperty.call(prototype, member)) {
253 newPrototype[member] = prototype[member]; 255 newPrototype[member] = prototype[member];
254 } 256 }
255 } 257 }
256 } 258 }
257 } 259 }
258 for (var cls in pendingClasses) finishClass(cls); 260 for (var cls in pendingClasses) finishClass(cls);
259 }'''; 261 }''';
260 } 262 }
261 263
(...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after
819 buffer.add("$setterName: function(v) { " 821 buffer.add("$setterName: function(v) { "
820 "this.$fieldName = $helperName(v$additionalArgument); }"); 822 "this.$fieldName = $helperName(v$additionalArgument); }");
821 } 823 }
822 824
823 void emitClassConstructor(ClassElement classElement, CodeBuffer buffer) { 825 void emitClassConstructor(ClassElement classElement, CodeBuffer buffer) {
824 /* Do nothing. */ 826 /* Do nothing. */
825 } 827 }
826 828
827 void emitClassFields(ClassElement classElement, 829 void emitClassFields(ClassElement classElement,
828 CodeBuffer buffer, 830 CodeBuffer buffer,
829 bool emitEndingComma) { 831 { String superClass: "",
832 bool isNative: false,
833 bool emitEndingComma: false}) {
ngeoffray 2012/11/30 12:11:46 Please don't put emitEndingComma optional. Other m
erikcorry 2012/11/30 12:20:02 I'll revert this in a later CL.
834 assert(!isNative || superClass != "");
830 bool isFirstField = true; 835 bool isFirstField = true;
836 bool isAnythingOutput = false;
837 if (!isNative) {
838 buffer.add('"":"$superClass@');
839 isAnythingOutput = true;
840 }
831 visitClassFields(classElement, (Element member, 841 visitClassFields(classElement, (Element member,
832 String name, 842 String name,
833 bool needsGetter, 843 bool needsGetter,
834 bool needsSetter, 844 bool needsSetter,
835 bool needsCheckedSetter) { 845 bool needsCheckedSetter) {
836
837 if (!getterAndSetterCanBeImplementedByFieldSpec( 846 if (!getterAndSetterCanBeImplementedByFieldSpec(
838 member, name, needsGetter, needsSetter)) { 847 member, name, needsGetter, needsSetter)) {
839 return; 848 return;
840 } 849 }
841 850 if (!isNative || needsCheckedSetter || needsGetter || needsSetter) {
842 if (isFirstField) { 851 if (isFirstField) {
843 buffer.add('"": ['); 852 isFirstField = false;
844 isFirstField = false; 853 if (!isAnythingOutput) {
845 } else { 854 buffer.add('"":"');
846 buffer.add(", "); 855 isAnythingOutput = true;
856 }
857 } else {
858 buffer.add(".");
859 }
860 buffer.add('$name');
861 if (needsGetter && needsSetter) {
862 buffer.add(GETTER_SETTER_SUFFIX);
863 } else if (needsGetter) {
864 buffer.add(GETTER_SUFFIX);
865 } else if (needsSetter) {
866 buffer.add(SETTER_SUFFIX);
867 }
847 } 868 }
848 buffer.add('"$name'); 869 });
849 if (needsGetter && needsSetter) { 870 if (isAnythingOutput) {
850 buffer.add(GETTER_SETTER_SUFFIX);
851 } else if (needsGetter) {
852 buffer.add(GETTER_SUFFIX);
853 } else if (needsSetter) {
854 buffer.add(SETTER_SUFFIX);
855 }
856 buffer.add('"'); 871 buffer.add('"');
857 });
858 if (!isFirstField) {
859 // There was at least one field.
860 buffer.add(']');
861 if (emitEndingComma) { 872 if (emitEndingComma) {
862 buffer.add(','); 873 buffer.add(',');
863 } 874 }
864 } 875 }
865 } 876 }
866 877
867 /** Each getter/setter must be prefixed with a ",\n ". */ 878 /** Each getter/setter must be prefixed with a ",\n ". */
868 void emitClassGettersSetters(ClassElement classElement, 879 void emitClassGettersSetters(ClassElement classElement,
869 CodeBuffer buffer, 880 CodeBuffer buffer,
870 bool emitLeadingComma) { 881 bool emitLeadingComma) {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
940 needsDefineClass = true; 951 needsDefineClass = true;
941 String className = namer.getName(classElement); 952 String className = namer.getName(classElement);
942 ClassElement superclass = classElement.superclass; 953 ClassElement superclass = classElement.superclass;
943 String superName = ""; 954 String superName = "";
944 if (superclass != null) { 955 if (superclass != null) {
945 superName = namer.getName(superclass); 956 superName = namer.getName(superclass);
946 } 957 }
947 958
948 buffer.add('$classesCollector.$className = {'); 959 buffer.add('$classesCollector.$className = {');
949 emitClassConstructor(classElement, buffer); 960 emitClassConstructor(classElement, buffer);
950 emitClassFields(classElement, buffer, true); 961 emitClassFields(classElement, buffer, superClass: superName,
962 isNative: false, emitEndingComma: false);
951 // TODO(floitsch): the emitInstanceMember should simply always emit a ',\n'. 963 // TODO(floitsch): the emitInstanceMember should simply always emit a ',\n'.
952 // That does currently not work because the native classes have a different 964 // That does currently not work because the native classes have a different
953 // syntax. 965 // syntax.
954 buffer.add('\n "super": "$superName"'); 966 emitClassGettersSetters(classElement, buffer, false);
955 emitClassGettersSetters(classElement, buffer, true);
956 emitInstanceMembers(classElement, buffer, true); 967 emitInstanceMembers(classElement, buffer, true);
957 buffer.add('\n};\n\n'); 968 buffer.add('\n};\n\n');
958 } 969 }
959 970
960 void emitInterceptorMethods( 971 void emitInterceptorMethods(
961 void defineInstanceMember(String name, StringBuffer memberBuffer)) { 972 void defineInstanceMember(String name, StringBuffer memberBuffer)) {
962 JavaScriptBackend backend = compiler.backend; 973 JavaScriptBackend backend = compiler.backend;
963 // Emit forwarders for the ObjectInterceptor class. We need to 974 // Emit forwarders for the ObjectInterceptor class. We need to
964 // emit all possible sends on intercepted methods. 975 // emit all possible sends on intercepted methods.
965 for (Selector selector in backend.usedInterceptors) { 976 for (Selector selector in backend.usedInterceptors) {
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
1153 // in case it is used in spawnFunction. 1164 // in case it is used in spawnFunction.
1154 String fieldName = namer.STATIC_CLOSURE_NAME_NAME; 1165 String fieldName = namer.STATIC_CLOSURE_NAME_NAME;
1155 buffer.add('$fieldAccess.$fieldName = "$staticName";\n'); 1166 buffer.add('$fieldAccess.$fieldName = "$staticName";\n');
1156 } 1167 }
1157 } 1168 }
1158 1169
1159 void emitBoundClosureClassHeader(String mangledName, 1170 void emitBoundClosureClassHeader(String mangledName,
1160 String superName, 1171 String superName,
1161 String extraArgument, 1172 String extraArgument,
1162 CodeBuffer buffer) { 1173 CodeBuffer buffer) {
1163 extraArgument = extraArgument.isEmpty ? '' : ", '$extraArgument'"; 1174 extraArgument = extraArgument.isEmpty ? '' : ".$extraArgument";
1164 buffer.add(""" 1175 buffer.add("""
1165 $classesCollector.$mangledName = {'': 1176 $classesCollector.$mangledName = {'':
1166 ['self'$extraArgument, 'target'], 1177 \"$superName@self$extraArgument.target\",
1167 'super': '$superName',
1168 """); 1178 """);
1169 } 1179 }
1170 1180
1171 /** 1181 /**
1172 * Documentation wanted -- johnniwinther 1182 * Documentation wanted -- johnniwinther
1173 * 1183 *
1174 * Invariant: [member] must be a declaration element. 1184 * Invariant: [member] must be a declaration element.
1175 */ 1185 */
1176 void emitDynamicFunctionGetter(FunctionElement member, 1186 void emitDynamicFunctionGetter(FunctionElement member,
1177 DefineMemberFunction defineInstanceMember) { 1187 DefineMemberFunction defineInstanceMember) {
(...skipping 638 matching lines...) Expand 10 before | Expand all | Expand 10 after
1816 const String HOOKS_API_USAGE = """ 1826 const String HOOKS_API_USAGE = """
1817 // Generated by dart2js, the Dart to JavaScript compiler. 1827 // Generated by dart2js, the Dart to JavaScript compiler.
1818 // The code supports the following hooks: 1828 // The code supports the following hooks:
1819 // dartPrint(message) - if this function is defined it is called 1829 // dartPrint(message) - if this function is defined it is called
1820 // instead of the Dart [print] method. 1830 // instead of the Dart [print] method.
1821 // dartMainRunner(main) - if this function is defined, the Dart [main] 1831 // dartMainRunner(main) - if this function is defined, the Dart [main]
1822 // method will not be invoked directly. 1832 // method will not be invoked directly.
1823 // Instead, a closure that will invoke [main] is 1833 // Instead, a closure that will invoke [main] is
1824 // passed to [dartMainRunner]. 1834 // passed to [dartMainRunner].
1825 """; 1835 """;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698