| 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 library dart2js.js_emitter.full_emitter.class_emitter; | 5 library dart2js.js_emitter.full_emitter.class_emitter; |
| 6 | 6 |
| 7 import '../../common.dart'; | 7 import '../../common.dart'; |
| 8 import '../../common/names.dart' show Names; | 8 import '../../common/names.dart' show Names; |
| 9 import '../../common_elements.dart'; | 9 import '../../common_elements.dart'; |
| 10 import '../../elements/resolution_types.dart' show ResolutionDartType; | 10 import '../../elements/resolution_types.dart' show ResolutionDartType; |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 fieldNames = cls.fields.map((Field field) => field.name).toList(); | 95 fieldNames = cls.fields.map((Field field) => field.name).toList(); |
| 96 } | 96 } |
| 97 | 97 |
| 98 ClassElement classElement = cls.element; | 98 ClassElement classElement = cls.element; |
| 99 | 99 |
| 100 jsAst.Expression constructorAst = _stubGenerator.generateClassConstructor( | 100 jsAst.Expression constructorAst = _stubGenerator.generateClassConstructor( |
| 101 classElement, fieldNames, cls.hasRtiField); | 101 classElement, fieldNames, cls.hasRtiField); |
| 102 | 102 |
| 103 jsAst.Name constructorName = namer.className(classElement); | 103 jsAst.Name constructorName = namer.className(classElement); |
| 104 OutputUnit outputUnit = | 104 OutputUnit outputUnit = |
| 105 compiler.deferredLoadTask.outputUnitForElement(classElement); | 105 compiler.deferredLoadTask.outputUnitForEntity(classElement); |
| 106 emitter.assemblePrecompiledConstructor( | 106 emitter.assemblePrecompiledConstructor( |
| 107 outputUnit, constructorName, constructorAst, fieldNames); | 107 outputUnit, constructorName, constructorAst, fieldNames); |
| 108 } | 108 } |
| 109 | 109 |
| 110 /// Returns `true` if fields added. | 110 /// Returns `true` if fields added. |
| 111 bool emitFields(FieldContainer container, ClassBuilder builder, | 111 bool emitFields(FieldContainer container, ClassBuilder builder, |
| 112 {bool classIsNative: false, bool emitStatics: false}) { | 112 {bool classIsNative: false, bool emitStatics: false}) { |
| 113 Iterable<Field> fields; | 113 Iterable<Field> fields; |
| 114 if (container is Class) { | 114 if (container is Class) { |
| 115 if (emitStatics) { | 115 if (emitStatics) { |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 .isClassAccessibleByReflection(fieldElement.enclosingClass)) { | 199 .isClassAccessibleByReflection(fieldElement.enclosingClass)) { |
| 200 // TODO(redemption): Support field entities. | 200 // TODO(redemption): Support field entities. |
| 201 FieldElement element = fieldElement; | 201 FieldElement element = fieldElement; |
| 202 ResolutionDartType type = element.type; | 202 ResolutionDartType type = element.type; |
| 203 fieldNameParts.add(task.metadataCollector.reifyType(type)); | 203 fieldNameParts.add(task.metadataCollector.reifyType(type)); |
| 204 } | 204 } |
| 205 } | 205 } |
| 206 jsAst.Literal fieldNameAst = js.concatenateStrings(fieldNameParts); | 206 jsAst.Literal fieldNameAst = js.concatenateStrings(fieldNameParts); |
| 207 builder.addField(fieldNameAst); | 207 builder.addField(fieldNameAst); |
| 208 // Add 1 because adding a field to the class also requires a comma | 208 // Add 1 because adding a field to the class also requires a comma |
| 209 compiler.dumpInfoTask.registerElementAst(fieldElement, fieldNameAst); | 209 compiler.dumpInfoTask.registerEntityAst(fieldElement, fieldNameAst); |
| 210 fieldsAdded = true; | 210 fieldsAdded = true; |
| 211 } | 211 } |
| 212 } | 212 } |
| 213 | 213 |
| 214 if (hasMetadata) { | 214 if (hasMetadata) { |
| 215 builder.fieldMetadata = fieldMetadata; | 215 builder.fieldMetadata = fieldMetadata; |
| 216 } | 216 } |
| 217 return fieldsAdded; | 217 return fieldsAdded; |
| 218 } | 218 } |
| 219 | 219 |
| 220 /// Emits checked setters for fields. | 220 /// Emits checked setters for fields. |
| 221 void emitCheckedClassSetters(Class cls, ClassBuilder builder) { | 221 void emitCheckedClassSetters(Class cls, ClassBuilder builder) { |
| 222 if (cls.onlyForRti) return; | 222 if (cls.onlyForRti) return; |
| 223 | 223 |
| 224 for (StubMethod method in cls.checkedSetters) { | 224 for (StubMethod method in cls.checkedSetters) { |
| 225 MemberElement member = method.element; | 225 MemberElement member = method.element; |
| 226 assert(member != null); | 226 assert(member != null); |
| 227 jsAst.Expression code = method.code; | 227 jsAst.Expression code = method.code; |
| 228 jsAst.Name setterName = method.name; | 228 jsAst.Name setterName = method.name; |
| 229 compiler.dumpInfoTask | 229 compiler.dumpInfoTask |
| 230 .registerElementAst(member, builder.addProperty(setterName, code)); | 230 .registerEntityAst(member, builder.addProperty(setterName, code)); |
| 231 generateReflectionDataForFieldGetterOrSetter(member, setterName, builder, | 231 generateReflectionDataForFieldGetterOrSetter(member, setterName, builder, |
| 232 isGetter: false); | 232 isGetter: false); |
| 233 } | 233 } |
| 234 } | 234 } |
| 235 | 235 |
| 236 /// Emits getters/setters for fields if compiling in CSP mode. | 236 /// Emits getters/setters for fields if compiling in CSP mode. |
| 237 void emitClassGettersSettersForCSP(Class cls, ClassBuilder builder) { | 237 void emitClassGettersSettersForCSP(Class cls, ClassBuilder builder) { |
| 238 if (!compiler.options.useContentSecurityPolicy || cls.onlyForRti) return; | 238 if (!compiler.options.useContentSecurityPolicy || cls.onlyForRti) return; |
| 239 | 239 |
| 240 for (Field field in cls.fields) { | 240 for (Field field in cls.fields) { |
| 241 FieldElement member = field.element; | 241 FieldElement member = field.element; |
| 242 reporter.withCurrentElement(member, () { | 242 reporter.withCurrentElement(member, () { |
| 243 if (field.needsGetter) { | 243 if (field.needsGetter) { |
| 244 emitGetterForCSP(member, field.name, field.accessorName, builder); | 244 emitGetterForCSP(member, field.name, field.accessorName, builder); |
| 245 } | 245 } |
| 246 if (field.needsUncheckedSetter) { | 246 if (field.needsUncheckedSetter) { |
| 247 emitSetterForCSP(member, field.name, field.accessorName, builder); | 247 emitSetterForCSP(member, field.name, field.accessorName, builder); |
| 248 } | 248 } |
| 249 }); | 249 }); |
| 250 } | 250 } |
| 251 } | 251 } |
| 252 | 252 |
| 253 void emitStubs(Iterable<StubMethod> stubs, ClassBuilder builder) { | 253 void emitStubs(Iterable<StubMethod> stubs, ClassBuilder builder) { |
| 254 for (Method method in stubs) { | 254 for (Method method in stubs) { |
| 255 jsAst.Property property = builder.addProperty(method.name, method.code); | 255 jsAst.Property property = builder.addProperty(method.name, method.code); |
| 256 compiler.dumpInfoTask.registerElementAst(method.element, property); | 256 compiler.dumpInfoTask.registerEntityAst(method.element, property); |
| 257 } | 257 } |
| 258 } | 258 } |
| 259 | 259 |
| 260 /** | 260 /** |
| 261 * Documentation wanted -- johnniwinther | 261 * Documentation wanted -- johnniwinther |
| 262 * | 262 * |
| 263 * Invariant: [classElement] must be a declaration element. | 263 * Invariant: [classElement] must be a declaration element. |
| 264 */ | 264 */ |
| 265 void emitInstanceMembers(Class cls, ClassBuilder builder) { | 265 void emitInstanceMembers(Class cls, ClassBuilder builder) { |
| 266 ClassEntity classElement = cls.element; | 266 ClassEntity classElement = cls.element; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 '<>', new jsAst.ArrayInitializer(typeVariableProperties.toList())); | 334 '<>', new jsAst.ArrayInitializer(typeVariableProperties.toList())); |
| 335 } | 335 } |
| 336 } | 336 } |
| 337 | 337 |
| 338 List<jsAst.Property> statics = new List<jsAst.Property>(); | 338 List<jsAst.Property> statics = new List<jsAst.Property>(); |
| 339 ClassBuilder staticsBuilder = | 339 ClassBuilder staticsBuilder = |
| 340 new ClassBuilder.forStatics(classEntity, namer); | 340 new ClassBuilder.forStatics(classEntity, namer); |
| 341 if (emitFields(cls, staticsBuilder, emitStatics: true)) { | 341 if (emitFields(cls, staticsBuilder, emitStatics: true)) { |
| 342 jsAst.ObjectInitializer initializer = | 342 jsAst.ObjectInitializer initializer = |
| 343 staticsBuilder.toObjectInitializer(); | 343 staticsBuilder.toObjectInitializer(); |
| 344 compiler.dumpInfoTask.registerElementAst(classEntity, initializer); | 344 compiler.dumpInfoTask.registerEntityAst(classEntity, initializer); |
| 345 jsAst.Node property = initializer.properties.single; | 345 jsAst.Node property = initializer.properties.single; |
| 346 compiler.dumpInfoTask.registerElementAst(classEntity, property); | 346 compiler.dumpInfoTask.registerEntityAst(classEntity, property); |
| 347 statics.add(property); | 347 statics.add(property); |
| 348 } | 348 } |
| 349 | 349 |
| 350 // TODO(herhut): Do not grab statics out of the properties. | 350 // TODO(herhut): Do not grab statics out of the properties. |
| 351 ClassBuilder classProperties = | 351 ClassBuilder classProperties = |
| 352 emitter.classDescriptors[fragment]?.remove(classEntity); | 352 emitter.classDescriptors[fragment]?.remove(classEntity); |
| 353 if (classProperties != null) { | 353 if (classProperties != null) { |
| 354 statics.addAll(classProperties.properties); | 354 statics.addAll(classProperties.properties); |
| 355 } | 355 } |
| 356 | 356 |
| 357 if (!statics.isEmpty) { | 357 if (!statics.isEmpty) { |
| 358 classBuilder.addProperty( | 358 classBuilder.addProperty( |
| 359 namer.staticsPropertyName, // 'static' or its minified name. | 359 namer.staticsPropertyName, // 'static' or its minified name. |
| 360 new jsAst.ObjectInitializer(statics, isOneLiner: false)); | 360 new jsAst.ObjectInitializer(statics, isOneLiner: false)); |
| 361 } | 361 } |
| 362 | 362 |
| 363 // TODO(ahe): This method (generateClass) should return a jsAst.Expression. | 363 // TODO(ahe): This method (generateClass) should return a jsAst.Expression. |
| 364 jsAst.ObjectInitializer propertyValue = classBuilder.toObjectInitializer(); | 364 jsAst.ObjectInitializer propertyValue = classBuilder.toObjectInitializer(); |
| 365 compiler.dumpInfoTask | 365 compiler.dumpInfoTask |
| 366 .registerElementAst(classBuilder.element, propertyValue); | 366 .registerEntityAst(classBuilder.element, propertyValue); |
| 367 enclosingBuilder.addProperty(className, propertyValue); | 367 enclosingBuilder.addProperty(className, propertyValue); |
| 368 | 368 |
| 369 String reflectionName = | 369 String reflectionName = |
| 370 emitter.getReflectionClassName(classEntity, className); | 370 emitter.getReflectionClassName(classEntity, className); |
| 371 if (reflectionName != null) { | 371 if (reflectionName != null) { |
| 372 if (!backend.mirrorsData.isClassAccessibleByReflection(classEntity) || | 372 if (!backend.mirrorsData.isClassAccessibleByReflection(classEntity) || |
| 373 cls.onlyForRti) { | 373 cls.onlyForRti) { |
| 374 // TODO(herhut): Fix use of reflection name here. | 374 // TODO(herhut): Fix use of reflection name here. |
| 375 enclosingBuilder.addPropertyByName("+$reflectionName", js.number(0)); | 375 enclosingBuilder.addPropertyByName("+$reflectionName", js.number(0)); |
| 376 } else { | 376 } else { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 407 | 407 |
| 408 void emitGetterForCSP(FieldElement member, jsAst.Name fieldName, | 408 void emitGetterForCSP(FieldElement member, jsAst.Name fieldName, |
| 409 jsAst.Name accessorName, ClassBuilder builder) { | 409 jsAst.Name accessorName, ClassBuilder builder) { |
| 410 jsAst.Expression function = | 410 jsAst.Expression function = |
| 411 _stubGenerator.generateGetter(member, fieldName); | 411 _stubGenerator.generateGetter(member, fieldName); |
| 412 | 412 |
| 413 jsAst.Name getterName = namer.deriveGetterName(accessorName); | 413 jsAst.Name getterName = namer.deriveGetterName(accessorName); |
| 414 ClassElement cls = member.enclosingClass; | 414 ClassElement cls = member.enclosingClass; |
| 415 jsAst.Name className = namer.className(cls); | 415 jsAst.Name className = namer.className(cls); |
| 416 OutputUnit outputUnit = | 416 OutputUnit outputUnit = |
| 417 compiler.deferredLoadTask.outputUnitForElement(member); | 417 compiler.deferredLoadTask.outputUnitForEntity(member); |
| 418 emitter | 418 emitter |
| 419 .cspPrecompiledFunctionFor(outputUnit) | 419 .cspPrecompiledFunctionFor(outputUnit) |
| 420 .add(js('#.prototype.# = #', [className, getterName, function])); | 420 .add(js('#.prototype.# = #', [className, getterName, function])); |
| 421 if (backend.mirrorsData.isMemberAccessibleByReflection(member)) { | 421 if (backend.mirrorsData.isMemberAccessibleByReflection(member)) { |
| 422 emitter.cspPrecompiledFunctionFor(outputUnit).add(js( | 422 emitter.cspPrecompiledFunctionFor(outputUnit).add(js( |
| 423 '#.prototype.#.${namer.reflectableField} = 1', | 423 '#.prototype.#.${namer.reflectableField} = 1', |
| 424 [className, getterName])); | 424 [className, getterName])); |
| 425 } | 425 } |
| 426 } | 426 } |
| 427 | 427 |
| 428 void emitSetterForCSP(FieldElement member, jsAst.Name fieldName, | 428 void emitSetterForCSP(FieldElement member, jsAst.Name fieldName, |
| 429 jsAst.Name accessorName, ClassBuilder builder) { | 429 jsAst.Name accessorName, ClassBuilder builder) { |
| 430 jsAst.Expression function = | 430 jsAst.Expression function = |
| 431 _stubGenerator.generateSetter(member, fieldName); | 431 _stubGenerator.generateSetter(member, fieldName); |
| 432 | 432 |
| 433 jsAst.Name setterName = namer.deriveSetterName(accessorName); | 433 jsAst.Name setterName = namer.deriveSetterName(accessorName); |
| 434 ClassElement cls = member.enclosingClass; | 434 ClassElement cls = member.enclosingClass; |
| 435 jsAst.Name className = namer.className(cls); | 435 jsAst.Name className = namer.className(cls); |
| 436 OutputUnit outputUnit = | 436 OutputUnit outputUnit = |
| 437 compiler.deferredLoadTask.outputUnitForElement(member); | 437 compiler.deferredLoadTask.outputUnitForEntity(member); |
| 438 emitter | 438 emitter |
| 439 .cspPrecompiledFunctionFor(outputUnit) | 439 .cspPrecompiledFunctionFor(outputUnit) |
| 440 .add(js('#.prototype.# = #', [className, setterName, function])); | 440 .add(js('#.prototype.# = #', [className, setterName, function])); |
| 441 if (backend.mirrorsData.isMemberAccessibleByReflection(member)) { | 441 if (backend.mirrorsData.isMemberAccessibleByReflection(member)) { |
| 442 emitter.cspPrecompiledFunctionFor(outputUnit).add(js( | 442 emitter.cspPrecompiledFunctionFor(outputUnit).add(js( |
| 443 '#.prototype.#.${namer.reflectableField} = 1', | 443 '#.prototype.#.${namer.reflectableField} = 1', |
| 444 [className, setterName])); | 444 [className, setterName])); |
| 445 } | 445 } |
| 446 } | 446 } |
| 447 | 447 |
| 448 void generateReflectionDataForFieldGetterOrSetter( | 448 void generateReflectionDataForFieldGetterOrSetter( |
| 449 MemberElement member, jsAst.Name name, ClassBuilder builder, | 449 MemberElement member, jsAst.Name name, ClassBuilder builder, |
| 450 {bool isGetter}) { | 450 {bool isGetter}) { |
| 451 Selector selector = isGetter | 451 Selector selector = isGetter |
| 452 ? new Selector.getter(member.memberName.getter) | 452 ? new Selector.getter(member.memberName.getter) |
| 453 : new Selector.setter(member.memberName.setter); | 453 : new Selector.setter(member.memberName.setter); |
| 454 String reflectionName = emitter.getReflectionSelectorName(selector, name); | 454 String reflectionName = emitter.getReflectionSelectorName(selector, name); |
| 455 if (reflectionName != null) { | 455 if (reflectionName != null) { |
| 456 var reflectable = js( | 456 var reflectable = js( |
| 457 backend.mirrorsData.isMemberAccessibleByReflection(member) | 457 backend.mirrorsData.isMemberAccessibleByReflection(member) |
| 458 ? '1' | 458 ? '1' |
| 459 : '0'); | 459 : '0'); |
| 460 builder.addPropertyByName('+$reflectionName', reflectable); | 460 builder.addPropertyByName('+$reflectionName', reflectable); |
| 461 } | 461 } |
| 462 } | 462 } |
| 463 } | 463 } |
| OLD | NEW |