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