OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 dart2js.js_emitter; | 5 part of dart2js.js_emitter; |
6 | 6 |
7 class ClassEmitter extends CodeEmitterHelper { | 7 class ClassEmitter extends CodeEmitterHelper { |
8 | 8 |
9 ClassStubGenerator get _stubGenerator => | 9 ClassStubGenerator get _stubGenerator => |
10 new ClassStubGenerator(compiler, namer, backend); | 10 new ClassStubGenerator(compiler, namer, backend); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 var metadata = | 121 var metadata = |
122 task.metadataCollector.buildMetadataFunction(fieldElement); | 122 task.metadataCollector.buildMetadataFunction(fieldElement); |
123 if (metadata != null) { | 123 if (metadata != null) { |
124 hasMetadata = true; | 124 hasMetadata = true; |
125 } else { | 125 } else { |
126 metadata = new jsAst.LiteralNull(); | 126 metadata = new jsAst.LiteralNull(); |
127 } | 127 } |
128 fieldMetadata.add(metadata); | 128 fieldMetadata.add(metadata); |
129 recordMangledField(fieldElement, accessorName, | 129 recordMangledField(fieldElement, accessorName, |
130 namer.privateName(fieldElement.memberName)); | 130 namer.privateName(fieldElement.memberName)); |
131 String fieldName = name; | 131 List<jsAst.Literal> fieldNameParts = <jsAst.Literal>[]; |
132 String fieldCode = ''; | |
133 String reflectionMarker = ''; | |
134 if (!needsAccessor) { | 132 if (!needsAccessor) { |
135 // Emit field for constructor generation. | 133 // Emit field for constructor generation. |
136 assert(!classIsNative); | 134 assert(!classIsNative); |
| 135 fieldNameParts.add(js.stringPart(name)); |
137 } else { | 136 } else { |
138 // Emit (possibly renaming) field name so we can add accessors at | 137 // Emit (possibly renaming) field name so we can add accessors at |
139 // runtime. | 138 // runtime. |
140 if (name != accessorName) { | 139 if (name != accessorName) { |
141 fieldName = '$accessorName:$name'; | 140 fieldNameParts.add(js.stringPart(accessorName)); |
| 141 fieldNameParts.add(js.stringPart(':')); |
142 } | 142 } |
143 | 143 fieldNameParts.add(js.stringPart(name)); |
144 if (field.needsInterceptedGetter) { | 144 if (field.needsInterceptedGetter) { |
145 emitter.interceptorEmitter.interceptorInvocationNames.add( | 145 emitter.interceptorEmitter.interceptorInvocationNames.add( |
146 namer.getterForElement(fieldElement)); | 146 namer.getterForElement(fieldElement)); |
147 } | 147 } |
148 // TODO(16168): The setter creator only looks at the getter-name. | 148 // TODO(16168): The setter creator only looks at the getter-name. |
149 // Even though the setter could avoid the interceptor convention we | 149 // Even though the setter could avoid the interceptor convention we |
150 // currently still need to add the additional argument. | 150 // currently still need to add the additional argument. |
151 if (field.needsInterceptedGetter || field.needsInterceptedSetter) { | 151 if (field.needsInterceptedGetter || field.needsInterceptedSetter) { |
152 emitter.interceptorEmitter.interceptorInvocationNames.add( | 152 emitter.interceptorEmitter.interceptorInvocationNames.add( |
153 namer.setterForElement(fieldElement)); | 153 namer.setterForElement(fieldElement)); |
154 } | 154 } |
155 | 155 |
156 int code = field.getterFlags + (field.setterFlags << 2); | 156 int code = field.getterFlags + (field.setterFlags << 2); |
157 if (code == 0) { | 157 if (code == 0) { |
158 compiler.internalError(fieldElement, | 158 compiler.internalError(fieldElement, |
159 'Field code is 0 ($fieldElement).'); | 159 'Field code is 0 ($fieldElement).'); |
160 } else { | |
161 fieldCode = FIELD_CODE_CHARACTERS[code - FIRST_FIELD_CODE]; | |
162 } | 160 } |
| 161 fieldNameParts.add( |
| 162 js.stringPart(FIELD_CODE_CHARACTERS[code - FIRST_FIELD_CODE])); |
163 } | 163 } |
164 if (backend.isAccessibleByReflection(fieldElement)) { | 164 if (backend.isAccessibleByReflection(fieldElement)) { |
165 DartType type = fieldElement.type; | 165 DartType type = fieldElement.type; |
166 reflectionMarker = '-${task.metadataCollector.reifyType(type)}'; | 166 fieldNameParts..add(new jsAst.LiteralString('-')) |
| 167 ..add(task.metadataCollector.reifyType(type)); |
167 } | 168 } |
168 String builtFieldname = '$fieldName$fieldCode$reflectionMarker'; | 169 jsAst.Literal fieldNameAst = js.concatenateStrings(fieldNameParts); |
169 builder.addField(builtFieldname); | 170 builder.addField(fieldNameAst); |
170 // Add 1 because adding a field to the class also requires a comma | 171 // Add 1 because adding a field to the class also requires a comma |
171 compiler.dumpInfoTask.recordFieldNameSize(fieldElement, | 172 compiler.dumpInfoTask.registerElementAst(fieldElement, fieldNameAst); |
172 builtFieldname.length + 1); | |
173 fieldsAdded = true; | 173 fieldsAdded = true; |
174 } | 174 } |
175 } | 175 } |
176 | 176 |
177 if (hasMetadata) { | 177 if (hasMetadata) { |
178 builder.fieldMetadata = fieldMetadata; | 178 builder.fieldMetadata = fieldMetadata; |
179 } | 179 } |
180 return fieldsAdded; | 180 return fieldsAdded; |
181 } | 181 } |
182 | 182 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
250 // them. Note that this helper is invoked before analyzing the | 250 // them. Note that this helper is invoked before analyzing the |
251 // full JS script. | 251 // full JS script. |
252 emitter.nsmEmitter.emitNoSuchMethodHandlers(builder.addProperty); | 252 emitter.nsmEmitter.emitNoSuchMethodHandlers(builder.addProperty); |
253 } | 253 } |
254 } | 254 } |
255 | 255 |
256 /// Emits the members from the model. | 256 /// Emits the members from the model. |
257 void emitRuntimeTypeInformation(Class cls, ClassBuilder builder) { | 257 void emitRuntimeTypeInformation(Class cls, ClassBuilder builder) { |
258 assert(builder.functionType == null); | 258 assert(builder.functionType == null); |
259 if (cls.functionTypeIndex != null) { | 259 if (cls.functionTypeIndex != null) { |
260 builder.functionType = '${cls.functionTypeIndex}'; | 260 builder.functionType = cls.functionTypeIndex; |
261 } | 261 } |
262 | 262 |
263 for (Method method in cls.isChecks) { | 263 for (Method method in cls.isChecks) { |
264 builder.addProperty(method.name, method.code); | 264 builder.addProperty(method.name, method.code); |
265 } | 265 } |
266 } | 266 } |
267 | 267 |
268 void emitNativeInfo(Class cls, ClassBuilder builder) { | 268 void emitNativeInfo(Class cls, ClassBuilder builder) { |
269 if (cls.nativeInfo != null) { | 269 if (cls.nativeInfo != null) { |
270 builder.addProperty(namer.nativeSpecProperty, js.string(cls.nativeInfo)); | 270 builder.addProperty(namer.nativeSpecProperty, js.string(cls.nativeInfo)); |
271 } | 271 } |
272 } | 272 } |
273 | 273 |
274 void emitClassBuilderWithReflectionData(Class cls, | 274 void emitClassBuilderWithReflectionData(Class cls, |
275 ClassBuilder classBuilder, | 275 ClassBuilder classBuilder, |
276 ClassBuilder enclosingBuilder, | 276 ClassBuilder enclosingBuilder, |
277 Fragment fragment) { | 277 Fragment fragment) { |
278 ClassElement classElement = cls.element; | 278 ClassElement classElement = cls.element; |
279 String className = cls.name; | 279 String className = cls.name; |
280 | 280 |
281 var metadata = task.metadataCollector.buildMetadataFunction(classElement); | 281 var metadata = task.metadataCollector.buildMetadataFunction(classElement); |
282 if (metadata != null) { | 282 if (metadata != null) { |
283 classBuilder.addProperty("@", metadata); | 283 classBuilder.addProperty("@", metadata); |
284 } | 284 } |
285 | 285 |
286 if (backend.isAccessibleByReflection(classElement)) { | 286 if (backend.isAccessibleByReflection(classElement)) { |
287 List<DartType> typeVars = classElement.typeVariables; | 287 List<DartType> typeVars = classElement.typeVariables; |
288 Iterable typeVariableProperties = emitter.typeVariableHandler | 288 Iterable typeVariableProperties = emitter.typeVariableHandler |
289 .typeVariablesOf(classElement).map(js.number); | 289 .typeVariablesOf(classElement); |
290 | 290 |
291 ClassElement superclass = classElement.superclass; | 291 ClassElement superclass = classElement.superclass; |
292 bool hasSuper = superclass != null; | 292 bool hasSuper = superclass != null; |
293 if ((!typeVariableProperties.isEmpty && !hasSuper) || | 293 if ((!typeVariableProperties.isEmpty && !hasSuper) || |
294 (hasSuper && !equalElements(superclass.typeVariables, typeVars))) { | 294 (hasSuper && !equalElements(superclass.typeVariables, typeVars))) { |
295 classBuilder.addProperty('<>', | 295 classBuilder.addProperty('<>', |
296 new jsAst.ArrayInitializer(typeVariableProperties.toList())); | 296 new jsAst.ArrayInitializer(typeVariableProperties.toList())); |
297 } | 297 } |
298 } | 298 } |
299 | 299 |
300 List<jsAst.Property> statics = new List<jsAst.Property>(); | 300 List<jsAst.Property> statics = new List<jsAst.Property>(); |
301 ClassBuilder staticsBuilder = new ClassBuilder(classElement, namer); | 301 ClassBuilder staticsBuilder = new ClassBuilder(classElement, namer); |
302 if (emitFields(cls, staticsBuilder, emitStatics: true)) { | 302 if (emitFields(cls, staticsBuilder, emitStatics: true)) { |
303 jsAst.ObjectInitializer initializer = | 303 jsAst.ObjectInitializer initializer = |
304 staticsBuilder.toObjectInitializer(); | 304 staticsBuilder.toObjectInitializer(compiler); |
305 compiler.dumpInfoTask.registerElementAst(classElement, | 305 compiler.dumpInfoTask.registerElementAst(classElement, |
306 initializer); | 306 initializer); |
307 jsAst.Node property = initializer.properties.single; | 307 jsAst.Node property = initializer.properties.single; |
308 compiler.dumpInfoTask.registerElementAst(classElement, property); | 308 compiler.dumpInfoTask.registerElementAst(classElement, property); |
309 statics.add(property); | 309 statics.add(property); |
310 } | 310 } |
311 | 311 |
312 // TODO(herhut): Do not grab statics out of the properties. | 312 // TODO(herhut): Do not grab statics out of the properties. |
313 ClassBuilder classProperties = | 313 ClassBuilder classProperties = |
314 emitter.elementDescriptors[fragment].remove(classElement); | 314 emitter.elementDescriptors[fragment].remove(classElement); |
315 if (classProperties != null) { | 315 if (classProperties != null) { |
316 statics.addAll(classProperties.properties); | 316 statics.addAll(classProperties.properties); |
317 } | 317 } |
318 | 318 |
319 if (!statics.isEmpty) { | 319 if (!statics.isEmpty) { |
320 classBuilder.addProperty('static', new jsAst.ObjectInitializer(statics)); | 320 classBuilder.addProperty('static', new jsAst.ObjectInitializer(statics)); |
321 } | 321 } |
322 | 322 |
323 // TODO(ahe): This method (generateClass) should return a jsAst.Expression. | 323 // TODO(ahe): This method (generateClass) should return a jsAst.Expression. |
324 jsAst.ObjectInitializer propertyValue = classBuilder.toObjectInitializer(); | 324 jsAst.ObjectInitializer propertyValue = |
| 325 classBuilder.toObjectInitializer(compiler); |
325 compiler.dumpInfoTask.registerElementAst(classBuilder.element, propertyValue
); | 326 compiler.dumpInfoTask.registerElementAst(classBuilder.element, propertyValue
); |
326 enclosingBuilder.addProperty(className, propertyValue); | 327 enclosingBuilder.addProperty(className, propertyValue); |
327 | 328 |
328 String reflectionName = emitter.getReflectionName(classElement, className); | 329 String reflectionName = emitter.getReflectionName(classElement, className); |
329 if (reflectionName != null) { | 330 if (reflectionName != null) { |
330 if (!backend.isAccessibleByReflection(classElement)) { | 331 if (!backend.isAccessibleByReflection(classElement)) { |
331 enclosingBuilder.addProperty("+$reflectionName", js.number(0)); | 332 enclosingBuilder.addProperty("+$reflectionName", js.number(0)); |
332 } else { | 333 } else { |
333 List<int> types = <int>[]; | 334 List<jsAst.Expression> types = <jsAst.Expression>[]; |
334 if (classElement.supertype != null) { | 335 if (classElement.supertype != null) { |
335 types.add(task.metadataCollector.reifyType(classElement.supertype)); | 336 types.add(task.metadataCollector.reifyType(classElement.supertype)); |
336 } | 337 } |
337 for (DartType interface in classElement.interfaces) { | 338 for (DartType interface in classElement.interfaces) { |
338 types.add(task.metadataCollector.reifyType(interface)); | 339 types.add(task.metadataCollector.reifyType(interface)); |
339 } | 340 } |
340 enclosingBuilder.addProperty("+$reflectionName", js.numArray(types)); | 341 enclosingBuilder.addProperty("+$reflectionName", |
| 342 new jsAst.ArrayInitializer(types)); |
341 } | 343 } |
342 } | 344 } |
343 } | 345 } |
344 | 346 |
345 /** | 347 /** |
346 * Invokes [f] for each of the fields of [element]. | 348 * Invokes [f] for each of the fields of [element]. |
347 * | 349 * |
348 * [element] must be a [ClassElement] or a [LibraryElement]. | 350 * [element] must be a [ClassElement] or a [LibraryElement]. |
349 * | 351 * |
350 * If [element] is a [ClassElement], the static fields of the class are | 352 * If [element] is a [ClassElement], the static fields of the class are |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
546 ? new Selector.getter(member.name, member.library) | 548 ? new Selector.getter(member.name, member.library) |
547 : new Selector.setter(member.name, member.library); | 549 : new Selector.setter(member.name, member.library); |
548 String reflectionName = emitter.getReflectionName(selector, name); | 550 String reflectionName = emitter.getReflectionName(selector, name); |
549 if (reflectionName != null) { | 551 if (reflectionName != null) { |
550 var reflectable = | 552 var reflectable = |
551 js(backend.isAccessibleByReflection(member) ? '1' : '0'); | 553 js(backend.isAccessibleByReflection(member) ? '1' : '0'); |
552 builder.addProperty('+$reflectionName', reflectable); | 554 builder.addProperty('+$reflectionName', reflectable); |
553 } | 555 } |
554 } | 556 } |
555 } | 557 } |
OLD | NEW |