Chromium Code Reviews| 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); |
| 11 | 11 |
| 12 /** | 12 /** |
| 13 * Documentation wanted -- johnniwinther | 13 * Documentation wanted -- johnniwinther |
| 14 */ | 14 */ |
| 15 void emitClass(Class cls, ClassBuilder enclosingBuilder, Fragment fragment) { | 15 void emitClass(Class cls, ClassBuilder enclosingBuilder, Fragment fragment) { |
| 16 ClassElement classElement = cls.element; | 16 ClassElement classElement = cls.element; |
| 17 | 17 |
| 18 assert(invariant(classElement, classElement.isDeclaration)); | 18 assert(invariant(classElement, classElement.isDeclaration)); |
| 19 | 19 |
| 20 emitter.needsClassSupport = true; | 20 emitter.needsClassSupport = true; |
| 21 | 21 |
| 22 ClassElement superclass = classElement.superclass; | 22 ClassElement superclass = classElement.superclass; |
| 23 String superName = ""; | 23 jsAst.Name superName; |
| 24 if (superclass != null) { | 24 if (superclass != null) { |
| 25 superName = namer.className(superclass); | 25 superName = namer.className(superclass); |
| 26 } | 26 } |
| 27 | 27 |
| 28 if (cls.isMixinApplication) { | 28 if (cls.isMixinApplication) { |
| 29 MixinApplication mixinApplication = cls; | 29 MixinApplication mixinApplication = cls; |
| 30 String mixinName = mixinApplication.mixinClass.name; | 30 jsAst.Name mixinName = mixinApplication.mixinClass.name; |
| 31 superName = '$superName+$mixinName'; | 31 superName = |
| 32 new CompoundName([superName, Namer.literalPlus, mixinName]); | |
| 32 emitter.needsMixinSupport = true; | 33 emitter.needsMixinSupport = true; |
| 33 } | 34 } |
| 34 | 35 |
| 35 ClassBuilder builder = new ClassBuilder(classElement, namer); | 36 ClassBuilder builder = new ClassBuilder.forClass(classElement, namer); |
| 36 builder.superName = superName; | 37 builder.superName = superName; |
| 37 emitConstructorsForCSP(cls); | 38 emitConstructorsForCSP(cls); |
| 38 emitFields(cls, builder); | 39 emitFields(cls, builder); |
| 39 emitCheckedClassSetters(cls, builder); | 40 emitCheckedClassSetters(cls, builder); |
| 40 emitClassGettersSettersForCSP(cls, builder); | 41 emitClassGettersSettersForCSP(cls, builder); |
| 41 emitInstanceMembers(cls, builder); | 42 emitInstanceMembers(cls, builder); |
| 42 emitStubs(cls.callStubs, builder); | 43 emitStubs(cls.callStubs, builder); |
| 43 emitStubs(cls.typeVariableReaderStubs, builder); | 44 emitStubs(cls.typeVariableReaderStubs, builder); |
| 44 emitRuntimeTypeInformation(cls, builder); | 45 emitRuntimeTypeInformation(cls, builder); |
| 45 emitNativeInfo(cls, builder); | 46 emitNativeInfo(cls, builder); |
| 46 | 47 |
| 47 if (classElement == backend.closureClass) { | 48 if (classElement == backend.closureClass) { |
| 48 // We add a special getter here to allow for tearing off a closure from | 49 // We add a special getter here to allow for tearing off a closure from |
| 49 // itself. | 50 // itself. |
| 50 jsAst.Fun function = js('function() { return this; }'); | 51 jsAst.Fun function = js('function() { return this; }'); |
| 51 String name = namer.getterForMember(Selector.CALL_NAME); | 52 jsAst.Name name = namer.getterForMember(Selector.CALL_NAME); |
| 52 builder.addProperty(name, function); | 53 builder.addProperty(name, function); |
| 53 } | 54 } |
| 54 | 55 |
| 55 emitClassBuilderWithReflectionData(cls, builder, enclosingBuilder, | 56 emitClassBuilderWithReflectionData(cls, builder, enclosingBuilder, |
| 56 fragment); | 57 fragment); |
| 57 } | 58 } |
| 58 /** | 59 /** |
| 59 * Emits the precompiled constructor when in CSP mode. | 60 * Emits the precompiled constructor when in CSP mode. |
| 60 */ | 61 */ |
| 61 void emitConstructorsForCSP(Class cls) { | 62 void emitConstructorsForCSP(Class cls) { |
| 62 List<String> fieldNames = <String>[]; | 63 List<String> fieldNames = <String>[]; |
| 63 | 64 |
| 64 if (!compiler.useContentSecurityPolicy) return; | 65 if (!compiler.useContentSecurityPolicy) return; |
| 65 | 66 |
| 66 if (!cls.onlyForRti && !cls.isNative) { | 67 if (!cls.onlyForRti && !cls.isNative) { |
| 67 fieldNames = cls.fields.map((Field field) => field.name).toList(); | 68 fieldNames = cls.fields.map((Field field) => field.name).toList(); |
| 68 } | 69 } |
| 69 | 70 |
| 70 ClassElement classElement = cls.element; | 71 ClassElement classElement = cls.element; |
| 71 | 72 |
| 72 jsAst.Expression constructorAst = | 73 jsAst.Expression constructorAst = |
| 73 _stubGenerator.generateClassConstructor(classElement, fieldNames); | 74 _stubGenerator.generateClassConstructor(classElement, fieldNames); |
| 74 | 75 |
| 75 String constructorName = namer.className(classElement); | 76 jsAst.Name constructorName = namer.className(classElement); |
| 76 OutputUnit outputUnit = | 77 OutputUnit outputUnit = |
| 77 compiler.deferredLoadTask.outputUnitForElement(classElement); | 78 compiler.deferredLoadTask.outputUnitForElement(classElement); |
| 78 emitter.assemblePrecompiledConstructor( | 79 emitter.assemblePrecompiledConstructor( |
| 79 outputUnit, constructorName, constructorAst, fieldNames); | 80 outputUnit, constructorName, constructorAst, fieldNames); |
| 80 } | 81 } |
| 81 | 82 |
| 82 /// Returns `true` if fields added. | 83 /// Returns `true` if fields added. |
| 83 bool emitFields(FieldContainer container, | 84 bool emitFields(FieldContainer container, |
| 84 ClassBuilder builder, | 85 ClassBuilder builder, |
| 85 { bool classIsNative: false, | 86 { bool classIsNative: false, |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 98 assert(emitStatics); | 99 assert(emitStatics); |
| 99 fields = container.staticFieldsForReflection; | 100 fields = container.staticFieldsForReflection; |
| 100 } | 101 } |
| 101 | 102 |
| 102 var fieldMetadata = []; | 103 var fieldMetadata = []; |
| 103 bool hasMetadata = false; | 104 bool hasMetadata = false; |
| 104 bool fieldsAdded = false; | 105 bool fieldsAdded = false; |
| 105 | 106 |
| 106 for (Field field in fields) { | 107 for (Field field in fields) { |
| 107 FieldElement fieldElement = field.element; | 108 FieldElement fieldElement = field.element; |
| 108 String name = field.name; | 109 jsAst.Name name = field.name; |
| 109 String accessorName = field.accessorName; | 110 jsAst.Name accessorName = field.accessorName; |
| 110 bool needsGetter = field.needsGetter; | 111 bool needsGetter = field.needsGetter; |
| 111 bool needsSetter = field.needsUncheckedSetter; | 112 bool needsSetter = field.needsUncheckedSetter; |
| 112 | 113 |
| 113 // Ignore needsCheckedSetter - that is handled below. | 114 // Ignore needsCheckedSetter - that is handled below. |
| 114 bool needsAccessor = (needsGetter || needsSetter); | 115 bool needsAccessor = (needsGetter || needsSetter); |
| 115 // We need to output the fields for non-native classes so we can auto- | 116 // We need to output the fields for non-native classes so we can auto- |
| 116 // generate the constructor. For native classes there are no | 117 // generate the constructor. For native classes there are no |
| 117 // constructors, so we don't need the fields unless we are generating | 118 // constructors, so we don't need the fields unless we are generating |
| 118 // accessors at runtime. | 119 // accessors at runtime. |
| 119 bool needsFieldsForConstructor = !emitStatics && !classIsNative; | 120 bool needsFieldsForConstructor = !emitStatics && !classIsNative; |
| 120 if (needsFieldsForConstructor || needsAccessor) { | 121 if (needsFieldsForConstructor || needsAccessor) { |
| 121 var metadata = | 122 var metadata = |
| 122 task.metadataCollector.buildMetadataFunction(fieldElement); | 123 task.metadataCollector.buildMetadataFunction(fieldElement); |
| 123 if (metadata != null) { | 124 if (metadata != null) { |
| 124 hasMetadata = true; | 125 hasMetadata = true; |
| 125 } else { | 126 } else { |
| 126 metadata = new jsAst.LiteralNull(); | 127 metadata = new jsAst.LiteralNull(); |
| 127 } | 128 } |
| 128 fieldMetadata.add(metadata); | 129 fieldMetadata.add(metadata); |
| 129 recordMangledField(fieldElement, accessorName, | 130 recordMangledField(fieldElement, accessorName, |
| 130 namer.privateName(fieldElement.memberName)); | 131 namer.privateName(fieldElement.memberName)); |
| 131 List<jsAst.Literal> fieldNameParts = <jsAst.Literal>[]; | 132 List<jsAst.Literal> fieldNameParts = <jsAst.Literal>[]; |
| 132 if (!needsAccessor) { | 133 if (!needsAccessor) { |
| 133 // Emit field for constructor generation. | 134 // Emit field for constructor generation. |
| 134 assert(!classIsNative); | 135 assert(!classIsNative); |
| 135 fieldNameParts.add(js.stringPart(name)); | 136 fieldNameParts.add(name); |
| 136 } else { | 137 } else { |
| 137 // Emit (possibly renaming) field name so we can add accessors at | 138 // Emit (possibly renaming) field name so we can add accessors at |
| 138 // runtime. | 139 // runtime. |
| 139 if (name != accessorName) { | 140 if (name != accessorName) { |
| 140 fieldNameParts.add(js.stringPart(accessorName)); | 141 fieldNameParts.add(accessorName); |
| 141 fieldNameParts.add(js.stringPart(':')); | 142 fieldNameParts.add(js.stringPart(':')); |
| 142 } | 143 } |
| 143 fieldNameParts.add(js.stringPart(name)); | 144 fieldNameParts.add(name); |
| 144 if (field.needsInterceptedGetter) { | 145 if (field.needsInterceptedGetter) { |
| 145 emitter.interceptorEmitter.interceptorInvocationNames.add( | 146 emitter.interceptorEmitter.interceptorInvocationNames.add( |
| 146 namer.getterForElement(fieldElement)); | 147 namer.getterForElement(fieldElement)); |
| 147 } | 148 } |
| 148 // TODO(16168): The setter creator only looks at the getter-name. | 149 // TODO(16168): The setter creator only looks at the getter-name. |
| 149 // Even though the setter could avoid the interceptor convention we | 150 // Even though the setter could avoid the interceptor convention we |
| 150 // currently still need to add the additional argument. | 151 // currently still need to add the additional argument. |
| 151 if (field.needsInterceptedGetter || field.needsInterceptedSetter) { | 152 if (field.needsInterceptedGetter || field.needsInterceptedSetter) { |
| 152 emitter.interceptorEmitter.interceptorInvocationNames.add( | 153 emitter.interceptorEmitter.interceptorInvocationNames.add( |
| 153 namer.setterForElement(fieldElement)); | 154 namer.setterForElement(fieldElement)); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 268 builder.functionType = cls.functionTypeIndex; | 269 builder.functionType = cls.functionTypeIndex; |
| 269 } | 270 } |
| 270 | 271 |
| 271 for (Method method in cls.isChecks) { | 272 for (Method method in cls.isChecks) { |
| 272 builder.addProperty(method.name, method.code); | 273 builder.addProperty(method.name, method.code); |
| 273 } | 274 } |
| 274 } | 275 } |
| 275 | 276 |
| 276 void emitNativeInfo(Class cls, ClassBuilder builder) { | 277 void emitNativeInfo(Class cls, ClassBuilder builder) { |
| 277 if (cls.nativeInfo != null) { | 278 if (cls.nativeInfo != null) { |
| 278 builder.addProperty(namer.nativeSpecProperty, js.string(cls.nativeInfo)); | 279 builder.addPropertyByName(namer.nativeSpecProperty, cls.nativeInfo); |
| 279 } | 280 } |
| 280 } | 281 } |
| 281 | 282 |
| 282 void emitClassBuilderWithReflectionData(Class cls, | 283 void emitClassBuilderWithReflectionData(Class cls, |
| 283 ClassBuilder classBuilder, | 284 ClassBuilder classBuilder, |
| 284 ClassBuilder enclosingBuilder, | 285 ClassBuilder enclosingBuilder, |
| 285 Fragment fragment) { | 286 Fragment fragment) { |
| 286 ClassElement classElement = cls.element; | 287 ClassElement classElement = cls.element; |
| 287 String className = cls.name; | 288 jsAst.Name className = cls.name; |
| 288 | 289 |
| 289 var metadata = task.metadataCollector.buildMetadataFunction(classElement); | 290 var metadata = task.metadataCollector.buildMetadataFunction(classElement); |
| 290 if (metadata != null) { | 291 if (metadata != null) { |
| 291 classBuilder.addProperty("@", metadata); | 292 classBuilder.addPropertyByName("@", metadata); |
| 292 } | 293 } |
| 293 | 294 |
| 294 if (backend.isAccessibleByReflection(classElement)) { | 295 if (backend.isAccessibleByReflection(classElement)) { |
| 295 List<DartType> typeVars = classElement.typeVariables; | 296 List<DartType> typeVars = classElement.typeVariables; |
| 296 Iterable typeVariableProperties = emitter.typeVariableHandler | 297 Iterable typeVariableProperties = emitter.typeVariableHandler |
| 297 .typeVariablesOf(classElement); | 298 .typeVariablesOf(classElement); |
| 298 | 299 |
| 299 ClassElement superclass = classElement.superclass; | 300 ClassElement superclass = classElement.superclass; |
| 300 bool hasSuper = superclass != null; | 301 bool hasSuper = superclass != null; |
| 301 if ((!typeVariableProperties.isEmpty && !hasSuper) || | 302 if ((!typeVariableProperties.isEmpty && !hasSuper) || |
| 302 (hasSuper && !equalElements(superclass.typeVariables, typeVars))) { | 303 (hasSuper && !equalElements(superclass.typeVariables, typeVars))) { |
| 303 classBuilder.addProperty('<>', | 304 classBuilder.addPropertyByName('<>', |
| 304 new jsAst.ArrayInitializer(typeVariableProperties.toList())); | 305 new jsAst.ArrayInitializer(typeVariableProperties.toList())); |
| 305 } | 306 } |
| 306 } | 307 } |
| 307 | 308 |
| 308 List<jsAst.Property> statics = new List<jsAst.Property>(); | 309 List<jsAst.Property> statics = new List<jsAst.Property>(); |
| 309 ClassBuilder staticsBuilder = new ClassBuilder(classElement, namer); | 310 ClassBuilder staticsBuilder = |
| 311 new ClassBuilder.forStatics(classElement, namer); | |
| 310 if (emitFields(cls, staticsBuilder, emitStatics: true)) { | 312 if (emitFields(cls, staticsBuilder, emitStatics: true)) { |
| 311 jsAst.ObjectInitializer initializer = | 313 jsAst.ObjectInitializer initializer = |
| 312 staticsBuilder.toObjectInitializer(); | 314 staticsBuilder.toObjectInitializer(); |
| 313 compiler.dumpInfoTask.registerElementAst(classElement, | 315 compiler.dumpInfoTask.registerElementAst(classElement, |
| 314 initializer); | 316 initializer); |
| 315 jsAst.Node property = initializer.properties.single; | 317 jsAst.Node property = initializer.properties.single; |
| 316 compiler.dumpInfoTask.registerElementAst(classElement, property); | 318 compiler.dumpInfoTask.registerElementAst(classElement, property); |
| 317 statics.add(property); | 319 statics.add(property); |
| 318 } | 320 } |
| 319 | 321 |
| 320 // TODO(herhut): Do not grab statics out of the properties. | 322 // TODO(herhut): Do not grab statics out of the properties. |
| 321 ClassBuilder classProperties = | 323 ClassBuilder classProperties = |
| 322 emitter.elementDescriptors[fragment].remove(classElement); | 324 emitter.elementDescriptors[fragment].remove(classElement); |
| 323 if (classProperties != null) { | 325 if (classProperties != null) { |
| 324 statics.addAll(classProperties.properties); | 326 statics.addAll(classProperties.properties); |
| 325 } | 327 } |
| 326 | 328 |
| 327 if (!statics.isEmpty) { | 329 if (!statics.isEmpty) { |
| 328 classBuilder.addProperty('static', new jsAst.ObjectInitializer(statics)); | 330 classBuilder.addPropertyByName('static', new jsAst.ObjectInitializer(stati cs)); |
|
floitsch
2015/06/22 17:43:44
long line.
herhut
2015/06/23 13:26:31
Thanks!
| |
| 329 } | 331 } |
| 330 | 332 |
| 331 // TODO(ahe): This method (generateClass) should return a jsAst.Expression. | 333 // TODO(ahe): This method (generateClass) should return a jsAst.Expression. |
| 332 jsAst.ObjectInitializer propertyValue = | 334 jsAst.ObjectInitializer propertyValue = |
| 333 classBuilder.toObjectInitializer(); | 335 classBuilder.toObjectInitializer(); |
| 334 compiler.dumpInfoTask.registerElementAst(classBuilder.element, propertyValue ); | 336 compiler.dumpInfoTask.registerElementAst(classBuilder.element, propertyValue ); |
| 335 enclosingBuilder.addProperty(className, propertyValue); | 337 enclosingBuilder.addProperty(className, propertyValue); |
| 336 | 338 |
| 337 String reflectionName = emitter.getReflectionName(classElement, className); | 339 String reflectionName = emitter.getReflectionName(classElement, className); |
| 338 if (reflectionName != null) { | 340 if (reflectionName != null) { |
| 339 if (!backend.isAccessibleByReflection(classElement)) { | 341 if (!backend.isAccessibleByReflection(classElement)) { |
| 340 enclosingBuilder.addProperty("+$reflectionName", js.number(0)); | 342 // TODO(herhut): Fix use of reflection name here. |
| 343 enclosingBuilder.addPropertyByName("+$reflectionName", js.number(0)); | |
| 341 } else { | 344 } else { |
| 342 List<jsAst.Expression> types = <jsAst.Expression>[]; | 345 List<jsAst.Expression> types = <jsAst.Expression>[]; |
| 343 if (classElement.supertype != null) { | 346 if (classElement.supertype != null) { |
| 344 types.add(task.metadataCollector.reifyType(classElement.supertype)); | 347 types.add(task.metadataCollector.reifyType(classElement.supertype)); |
| 345 } | 348 } |
| 346 for (DartType interface in classElement.interfaces) { | 349 for (DartType interface in classElement.interfaces) { |
| 347 types.add(task.metadataCollector.reifyType(interface)); | 350 types.add(task.metadataCollector.reifyType(interface)); |
| 348 } | 351 } |
| 349 enclosingBuilder.addProperty("+$reflectionName", | 352 // TODO(herhut): Fix use of reflection name here. |
| 353 enclosingBuilder.addPropertyByName("+$reflectionName", | |
| 350 new jsAst.ArrayInitializer(types)); | 354 new jsAst.ArrayInitializer(types)); |
| 351 } | 355 } |
| 352 } | 356 } |
| 353 } | 357 } |
| 354 | 358 |
| 355 /** | 359 /** |
| 356 * Invokes [f] for each of the fields of [element]. | 360 * Invokes [f] for each of the fields of [element]. |
| 357 * | 361 * |
| 358 * [element] must be a [ClassElement] or a [LibraryElement]. | 362 * [element] must be a [ClassElement] or a [LibraryElement]. |
| 359 * | 363 * |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 403 bool needsGetter = false; | 407 bool needsGetter = false; |
| 404 bool needsSetter = false; | 408 bool needsSetter = false; |
| 405 if (isLibrary || isMixinNativeField || holder == element) { | 409 if (isLibrary || isMixinNativeField || holder == element) { |
| 406 needsGetter = fieldNeedsGetter(field); | 410 needsGetter = fieldNeedsGetter(field); |
| 407 needsSetter = fieldNeedsSetter(field); | 411 needsSetter = fieldNeedsSetter(field); |
| 408 } | 412 } |
| 409 | 413 |
| 410 if ((isInstantiated && !holder.isNative) | 414 if ((isInstantiated && !holder.isNative) |
| 411 || needsGetter | 415 || needsGetter |
| 412 || needsSetter) { | 416 || needsSetter) { |
| 413 String accessorName = namer.fieldAccessorName(field); | 417 jsAst.Name accessorName = namer.fieldAccessorName(field); |
| 414 String fieldName = namer.fieldPropertyName(field); | 418 jsAst.Name fieldName = namer.fieldPropertyName(field); |
| 415 bool needsCheckedSetter = false; | 419 bool needsCheckedSetter = false; |
| 416 if (compiler.enableTypeAssertions | 420 if (compiler.enableTypeAssertions |
| 417 && needsSetter | 421 && needsSetter |
| 418 && !canAvoidGeneratedCheckedSetter(field)) { | 422 && !canAvoidGeneratedCheckedSetter(field)) { |
| 419 needsCheckedSetter = true; | 423 needsCheckedSetter = true; |
| 420 needsSetter = false; | 424 needsSetter = false; |
| 421 } | 425 } |
| 422 // Getters and setters with suffixes will be generated dynamically. | 426 // Getters and setters with suffixes will be generated dynamically. |
| 423 f(field, fieldName, accessorName, needsGetter, needsSetter, | 427 f(field, fieldName, accessorName, needsGetter, needsSetter, |
| 424 needsCheckedSetter); | 428 needsCheckedSetter); |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 443 // If a class is not instantiated then we add the field just so we can | 447 // If a class is not instantiated then we add the field just so we can |
| 444 // generate the field getter/setter dynamically. Since this is only | 448 // generate the field getter/setter dynamically. Since this is only |
| 445 // allowed on fields that are in [element] we don't need to visit | 449 // allowed on fields that are in [element] we don't need to visit |
| 446 // superclasses for non-instantiated classes. | 450 // superclasses for non-instantiated classes. |
| 447 cls.implementation.forEachInstanceField( | 451 cls.implementation.forEachInstanceField( |
| 448 visitField, includeSuperAndInjectedMembers: isInstantiated); | 452 visitField, includeSuperAndInjectedMembers: isInstantiated); |
| 449 } | 453 } |
| 450 } | 454 } |
| 451 | 455 |
| 452 void recordMangledField(Element member, | 456 void recordMangledField(Element member, |
| 453 String accessorName, | 457 jsAst.Name accessorName, |
| 454 String memberName) { | 458 String memberName) { |
| 455 if (!backend.shouldRetainGetter(member)) return; | 459 if (!backend.shouldRetainGetter(member)) return; |
| 456 String previousName; | 460 String previousName; |
| 457 if (member.isInstanceMember) { | 461 if (member.isInstanceMember) { |
| 458 previousName = emitter.mangledFieldNames.putIfAbsent( | 462 previousName = emitter.mangledFieldNames.putIfAbsent( |
| 459 '${namer.getterPrefix}$accessorName', | 463 namer.deriveGetterName(accessorName), |
| 460 () => memberName); | 464 () => memberName); |
| 461 } else { | 465 } else { |
| 462 previousName = emitter.mangledGlobalFieldNames.putIfAbsent( | 466 previousName = emitter.mangledGlobalFieldNames.putIfAbsent( |
| 463 accessorName, | 467 accessorName, |
| 464 () => memberName); | 468 () => memberName); |
| 465 } | 469 } |
| 466 assert(invariant(member, previousName == memberName, | 470 assert(invariant(member, previousName == memberName, |
| 467 message: '$previousName != ${memberName}')); | 471 message: '$previousName != ${memberName}')); |
| 468 } | 472 } |
| 469 | 473 |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 494 } | 498 } |
| 495 | 499 |
| 496 bool canAvoidGeneratedCheckedSetter(VariableElement member) { | 500 bool canAvoidGeneratedCheckedSetter(VariableElement member) { |
| 497 // We never generate accessors for top-level/static fields. | 501 // We never generate accessors for top-level/static fields. |
| 498 if (!member.isInstanceMember) return true; | 502 if (!member.isInstanceMember) return true; |
| 499 DartType type = member.type; | 503 DartType type = member.type; |
| 500 return type.treatAsDynamic || (type.element == compiler.objectClass); | 504 return type.treatAsDynamic || (type.element == compiler.objectClass); |
| 501 } | 505 } |
| 502 | 506 |
| 503 void generateCheckedSetter(Element member, | 507 void generateCheckedSetter(Element member, |
| 504 String fieldName, | 508 jsAst.Name fieldName, |
| 505 String accessorName, | 509 jsAst.Name accessorName, |
| 506 ClassBuilder builder) { | 510 ClassBuilder builder) { |
| 507 jsAst.Expression code = backend.generatedCode[member]; | 511 jsAst.Expression code = backend.generatedCode[member]; |
| 508 assert(code != null); | 512 assert(code != null); |
| 509 String setterName = namer.deriveSetterName(accessorName); | 513 jsAst.Name setterName = namer.deriveSetterName(accessorName); |
| 510 compiler.dumpInfoTask.registerElementAst(member, | 514 compiler.dumpInfoTask.registerElementAst(member, |
| 511 builder.addProperty(setterName, code)); | 515 builder.addProperty(setterName, code)); |
| 512 generateReflectionDataForFieldGetterOrSetter( | 516 generateReflectionDataForFieldGetterOrSetter( |
| 513 member, setterName, builder, isGetter: false); | 517 member, setterName, builder, isGetter: false); |
| 514 } | 518 } |
| 515 | 519 |
| 516 void emitGetterForCSP(Element member, String fieldName, String accessorName, | 520 void emitGetterForCSP(Element member, jsAst.Name fieldName, |
| 521 jsAst.Name accessorName, | |
| 517 ClassBuilder builder) { | 522 ClassBuilder builder) { |
| 518 jsAst.Expression function = | 523 jsAst.Expression function = |
| 519 _stubGenerator.generateGetter(member, fieldName); | 524 _stubGenerator.generateGetter(member, fieldName); |
| 520 | 525 |
| 521 String getterName = namer.deriveGetterName(accessorName); | 526 jsAst.Name getterName = namer.deriveGetterName(accessorName); |
| 522 ClassElement cls = member.enclosingClass; | 527 ClassElement cls = member.enclosingClass; |
| 523 String className = namer.className(cls); | 528 jsAst.Name className = namer.className(cls); |
| 524 OutputUnit outputUnit = | 529 OutputUnit outputUnit = |
| 525 compiler.deferredLoadTask.outputUnitForElement(member); | 530 compiler.deferredLoadTask.outputUnitForElement(member); |
| 526 emitter.cspPrecompiledFunctionFor(outputUnit).add( | 531 emitter.cspPrecompiledFunctionFor(outputUnit).add( |
| 527 js('#.prototype.# = #', [className, getterName, function])); | 532 js('#.prototype.# = #', [className, getterName, function])); |
| 528 if (backend.isAccessibleByReflection(member)) { | 533 if (backend.isAccessibleByReflection(member)) { |
| 529 emitter.cspPrecompiledFunctionFor(outputUnit).add( | 534 emitter.cspPrecompiledFunctionFor(outputUnit).add( |
| 530 js('#.prototype.#.${namer.reflectableField} = 1', | 535 js('#.prototype.#.${namer.reflectableField} = 1', |
| 531 [className, getterName])); | 536 [className, getterName])); |
| 532 } | 537 } |
| 533 } | 538 } |
| 534 | 539 |
| 535 void emitSetterForCSP(Element member, String fieldName, String accessorName, | 540 void emitSetterForCSP(Element member, jsAst.Name fieldName, |
| 541 jsAst.Name accessorName, | |
| 536 ClassBuilder builder) { | 542 ClassBuilder builder) { |
| 537 jsAst.Expression function = | 543 jsAst.Expression function = |
| 538 _stubGenerator.generateSetter(member, fieldName); | 544 _stubGenerator.generateSetter(member, fieldName); |
| 539 | 545 |
| 540 String setterName = namer.deriveSetterName(accessorName); | 546 jsAst.Name setterName = namer.deriveSetterName(accessorName); |
| 541 ClassElement cls = member.enclosingClass; | 547 ClassElement cls = member.enclosingClass; |
| 542 String className = namer.className(cls); | 548 jsAst.Name className = namer.className(cls); |
| 543 OutputUnit outputUnit = | 549 OutputUnit outputUnit = |
| 544 compiler.deferredLoadTask.outputUnitForElement(member); | 550 compiler.deferredLoadTask.outputUnitForElement(member); |
| 545 emitter.cspPrecompiledFunctionFor(outputUnit).add( | 551 emitter.cspPrecompiledFunctionFor(outputUnit).add( |
| 546 js('#.prototype.# = #', [className, setterName, function])); | 552 js('#.prototype.# = #', [className, setterName, function])); |
| 547 if (backend.isAccessibleByReflection(member)) { | 553 if (backend.isAccessibleByReflection(member)) { |
| 548 emitter.cspPrecompiledFunctionFor(outputUnit).add( | 554 emitter.cspPrecompiledFunctionFor(outputUnit).add( |
| 549 js('#.prototype.#.${namer.reflectableField} = 1', | 555 js('#.prototype.#.${namer.reflectableField} = 1', |
| 550 [className, setterName])); | 556 [className, setterName])); |
| 551 } | 557 } |
| 552 } | 558 } |
| 553 | 559 |
| 554 void generateReflectionDataForFieldGetterOrSetter(Element member, | 560 void generateReflectionDataForFieldGetterOrSetter(Element member, |
| 555 String name, | 561 jsAst.Name name, |
| 556 ClassBuilder builder, | 562 ClassBuilder builder, |
| 557 {bool isGetter}) { | 563 {bool isGetter}) { |
| 558 Selector selector = isGetter | 564 Selector selector = isGetter |
| 559 ? new Selector.getter(member.name, member.library) | 565 ? new Selector.getter(member.name, member.library) |
| 560 : new Selector.setter(member.name, member.library); | 566 : new Selector.setter(member.name, member.library); |
| 561 String reflectionName = emitter.getReflectionName(selector, name); | 567 String reflectionName = emitter.getReflectionName(selector, name); |
| 562 if (reflectionName != null) { | 568 if (reflectionName != null) { |
| 563 var reflectable = | 569 var reflectable = |
| 564 js(backend.isAccessibleByReflection(member) ? '1' : '0'); | 570 js(backend.isAccessibleByReflection(member) ? '1' : '0'); |
| 565 builder.addProperty('+$reflectionName', reflectable); | 571 builder.addPropertyByName('+$reflectionName', reflectable); |
| 566 } | 572 } |
| 567 } | 573 } |
| 568 } | 574 } |
| OLD | NEW |