| 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', |
| 331 new jsAst.ObjectInitializer(statics)); |
| 329 } | 332 } |
| 330 | 333 |
| 331 // TODO(ahe): This method (generateClass) should return a jsAst.Expression. | 334 // TODO(ahe): This method (generateClass) should return a jsAst.Expression. |
| 332 jsAst.ObjectInitializer propertyValue = | 335 jsAst.ObjectInitializer propertyValue = |
| 333 classBuilder.toObjectInitializer(); | 336 classBuilder.toObjectInitializer(); |
| 334 compiler.dumpInfoTask.registerElementAst(classBuilder.element, propertyValue
); | 337 compiler.dumpInfoTask.registerElementAst(classBuilder.element, propertyValue
); |
| 335 enclosingBuilder.addProperty(className, propertyValue); | 338 enclosingBuilder.addProperty(className, propertyValue); |
| 336 | 339 |
| 337 String reflectionName = emitter.getReflectionName(classElement, className); | 340 String reflectionName = emitter.getReflectionName(classElement, className); |
| 338 if (reflectionName != null) { | 341 if (reflectionName != null) { |
| 339 if (!backend.isAccessibleByReflection(classElement)) { | 342 if (!backend.isAccessibleByReflection(classElement)) { |
| 340 enclosingBuilder.addProperty("+$reflectionName", js.number(0)); | 343 // TODO(herhut): Fix use of reflection name here. |
| 344 enclosingBuilder.addPropertyByName("+$reflectionName", js.number(0)); |
| 341 } else { | 345 } else { |
| 342 List<jsAst.Expression> types = <jsAst.Expression>[]; | 346 List<jsAst.Expression> types = <jsAst.Expression>[]; |
| 343 if (classElement.supertype != null) { | 347 if (classElement.supertype != null) { |
| 344 types.add(task.metadataCollector.reifyType(classElement.supertype)); | 348 types.add(task.metadataCollector.reifyType(classElement.supertype)); |
| 345 } | 349 } |
| 346 for (DartType interface in classElement.interfaces) { | 350 for (DartType interface in classElement.interfaces) { |
| 347 types.add(task.metadataCollector.reifyType(interface)); | 351 types.add(task.metadataCollector.reifyType(interface)); |
| 348 } | 352 } |
| 349 enclosingBuilder.addProperty("+$reflectionName", | 353 // TODO(herhut): Fix use of reflection name here. |
| 354 enclosingBuilder.addPropertyByName("+$reflectionName", |
| 350 new jsAst.ArrayInitializer(types)); | 355 new jsAst.ArrayInitializer(types)); |
| 351 } | 356 } |
| 352 } | 357 } |
| 353 } | 358 } |
| 354 | 359 |
| 355 /** | 360 /** |
| 356 * Invokes [f] for each of the fields of [element]. | 361 * Invokes [f] for each of the fields of [element]. |
| 357 * | 362 * |
| 358 * [element] must be a [ClassElement] or a [LibraryElement]. | 363 * [element] must be a [ClassElement] or a [LibraryElement]. |
| 359 * | 364 * |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 403 bool needsGetter = false; | 408 bool needsGetter = false; |
| 404 bool needsSetter = false; | 409 bool needsSetter = false; |
| 405 if (isLibrary || isMixinNativeField || holder == element) { | 410 if (isLibrary || isMixinNativeField || holder == element) { |
| 406 needsGetter = fieldNeedsGetter(field); | 411 needsGetter = fieldNeedsGetter(field); |
| 407 needsSetter = fieldNeedsSetter(field); | 412 needsSetter = fieldNeedsSetter(field); |
| 408 } | 413 } |
| 409 | 414 |
| 410 if ((isInstantiated && !holder.isNative) | 415 if ((isInstantiated && !holder.isNative) |
| 411 || needsGetter | 416 || needsGetter |
| 412 || needsSetter) { | 417 || needsSetter) { |
| 413 String accessorName = namer.fieldAccessorName(field); | 418 jsAst.Name accessorName = namer.fieldAccessorName(field); |
| 414 String fieldName = namer.fieldPropertyName(field); | 419 jsAst.Name fieldName = namer.fieldPropertyName(field); |
| 415 bool needsCheckedSetter = false; | 420 bool needsCheckedSetter = false; |
| 416 if (compiler.enableTypeAssertions | 421 if (compiler.enableTypeAssertions |
| 417 && needsSetter | 422 && needsSetter |
| 418 && !canAvoidGeneratedCheckedSetter(field)) { | 423 && !canAvoidGeneratedCheckedSetter(field)) { |
| 419 needsCheckedSetter = true; | 424 needsCheckedSetter = true; |
| 420 needsSetter = false; | 425 needsSetter = false; |
| 421 } | 426 } |
| 422 // Getters and setters with suffixes will be generated dynamically. | 427 // Getters and setters with suffixes will be generated dynamically. |
| 423 f(field, fieldName, accessorName, needsGetter, needsSetter, | 428 f(field, fieldName, accessorName, needsGetter, needsSetter, |
| 424 needsCheckedSetter); | 429 needsCheckedSetter); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 443 // If a class is not instantiated then we add the field just so we can | 448 // 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 | 449 // generate the field getter/setter dynamically. Since this is only |
| 445 // allowed on fields that are in [element] we don't need to visit | 450 // allowed on fields that are in [element] we don't need to visit |
| 446 // superclasses for non-instantiated classes. | 451 // superclasses for non-instantiated classes. |
| 447 cls.implementation.forEachInstanceField( | 452 cls.implementation.forEachInstanceField( |
| 448 visitField, includeSuperAndInjectedMembers: isInstantiated); | 453 visitField, includeSuperAndInjectedMembers: isInstantiated); |
| 449 } | 454 } |
| 450 } | 455 } |
| 451 | 456 |
| 452 void recordMangledField(Element member, | 457 void recordMangledField(Element member, |
| 453 String accessorName, | 458 jsAst.Name accessorName, |
| 454 String memberName) { | 459 String memberName) { |
| 455 if (!backend.shouldRetainGetter(member)) return; | 460 if (!backend.shouldRetainGetter(member)) return; |
| 456 String previousName; | 461 String previousName; |
| 457 if (member.isInstanceMember) { | 462 if (member.isInstanceMember) { |
| 458 previousName = emitter.mangledFieldNames.putIfAbsent( | 463 previousName = emitter.mangledFieldNames.putIfAbsent( |
| 459 '${namer.getterPrefix}$accessorName', | 464 namer.deriveGetterName(accessorName), |
| 460 () => memberName); | 465 () => memberName); |
| 461 } else { | 466 } else { |
| 462 previousName = emitter.mangledGlobalFieldNames.putIfAbsent( | 467 previousName = emitter.mangledGlobalFieldNames.putIfAbsent( |
| 463 accessorName, | 468 accessorName, |
| 464 () => memberName); | 469 () => memberName); |
| 465 } | 470 } |
| 466 assert(invariant(member, previousName == memberName, | 471 assert(invariant(member, previousName == memberName, |
| 467 message: '$previousName != ${memberName}')); | 472 message: '$previousName != ${memberName}')); |
| 468 } | 473 } |
| 469 | 474 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 494 } | 499 } |
| 495 | 500 |
| 496 bool canAvoidGeneratedCheckedSetter(VariableElement member) { | 501 bool canAvoidGeneratedCheckedSetter(VariableElement member) { |
| 497 // We never generate accessors for top-level/static fields. | 502 // We never generate accessors for top-level/static fields. |
| 498 if (!member.isInstanceMember) return true; | 503 if (!member.isInstanceMember) return true; |
| 499 DartType type = member.type; | 504 DartType type = member.type; |
| 500 return type.treatAsDynamic || (type.element == compiler.objectClass); | 505 return type.treatAsDynamic || (type.element == compiler.objectClass); |
| 501 } | 506 } |
| 502 | 507 |
| 503 void generateCheckedSetter(Element member, | 508 void generateCheckedSetter(Element member, |
| 504 String fieldName, | 509 jsAst.Name fieldName, |
| 505 String accessorName, | 510 jsAst.Name accessorName, |
| 506 ClassBuilder builder) { | 511 ClassBuilder builder) { |
| 507 jsAst.Expression code = backend.generatedCode[member]; | 512 jsAst.Expression code = backend.generatedCode[member]; |
| 508 assert(code != null); | 513 assert(code != null); |
| 509 String setterName = namer.deriveSetterName(accessorName); | 514 jsAst.Name setterName = namer.deriveSetterName(accessorName); |
| 510 compiler.dumpInfoTask.registerElementAst(member, | 515 compiler.dumpInfoTask.registerElementAst(member, |
| 511 builder.addProperty(setterName, code)); | 516 builder.addProperty(setterName, code)); |
| 512 generateReflectionDataForFieldGetterOrSetter( | 517 generateReflectionDataForFieldGetterOrSetter( |
| 513 member, setterName, builder, isGetter: false); | 518 member, setterName, builder, isGetter: false); |
| 514 } | 519 } |
| 515 | 520 |
| 516 void emitGetterForCSP(Element member, String fieldName, String accessorName, | 521 void emitGetterForCSP(Element member, jsAst.Name fieldName, |
| 522 jsAst.Name accessorName, |
| 517 ClassBuilder builder) { | 523 ClassBuilder builder) { |
| 518 jsAst.Expression function = | 524 jsAst.Expression function = |
| 519 _stubGenerator.generateGetter(member, fieldName); | 525 _stubGenerator.generateGetter(member, fieldName); |
| 520 | 526 |
| 521 String getterName = namer.deriveGetterName(accessorName); | 527 jsAst.Name getterName = namer.deriveGetterName(accessorName); |
| 522 ClassElement cls = member.enclosingClass; | 528 ClassElement cls = member.enclosingClass; |
| 523 String className = namer.className(cls); | 529 jsAst.Name className = namer.className(cls); |
| 524 OutputUnit outputUnit = | 530 OutputUnit outputUnit = |
| 525 compiler.deferredLoadTask.outputUnitForElement(member); | 531 compiler.deferredLoadTask.outputUnitForElement(member); |
| 526 emitter.cspPrecompiledFunctionFor(outputUnit).add( | 532 emitter.cspPrecompiledFunctionFor(outputUnit).add( |
| 527 js('#.prototype.# = #', [className, getterName, function])); | 533 js('#.prototype.# = #', [className, getterName, function])); |
| 528 if (backend.isAccessibleByReflection(member)) { | 534 if (backend.isAccessibleByReflection(member)) { |
| 529 emitter.cspPrecompiledFunctionFor(outputUnit).add( | 535 emitter.cspPrecompiledFunctionFor(outputUnit).add( |
| 530 js('#.prototype.#.${namer.reflectableField} = 1', | 536 js('#.prototype.#.${namer.reflectableField} = 1', |
| 531 [className, getterName])); | 537 [className, getterName])); |
| 532 } | 538 } |
| 533 } | 539 } |
| 534 | 540 |
| 535 void emitSetterForCSP(Element member, String fieldName, String accessorName, | 541 void emitSetterForCSP(Element member, jsAst.Name fieldName, |
| 542 jsAst.Name accessorName, |
| 536 ClassBuilder builder) { | 543 ClassBuilder builder) { |
| 537 jsAst.Expression function = | 544 jsAst.Expression function = |
| 538 _stubGenerator.generateSetter(member, fieldName); | 545 _stubGenerator.generateSetter(member, fieldName); |
| 539 | 546 |
| 540 String setterName = namer.deriveSetterName(accessorName); | 547 jsAst.Name setterName = namer.deriveSetterName(accessorName); |
| 541 ClassElement cls = member.enclosingClass; | 548 ClassElement cls = member.enclosingClass; |
| 542 String className = namer.className(cls); | 549 jsAst.Name className = namer.className(cls); |
| 543 OutputUnit outputUnit = | 550 OutputUnit outputUnit = |
| 544 compiler.deferredLoadTask.outputUnitForElement(member); | 551 compiler.deferredLoadTask.outputUnitForElement(member); |
| 545 emitter.cspPrecompiledFunctionFor(outputUnit).add( | 552 emitter.cspPrecompiledFunctionFor(outputUnit).add( |
| 546 js('#.prototype.# = #', [className, setterName, function])); | 553 js('#.prototype.# = #', [className, setterName, function])); |
| 547 if (backend.isAccessibleByReflection(member)) { | 554 if (backend.isAccessibleByReflection(member)) { |
| 548 emitter.cspPrecompiledFunctionFor(outputUnit).add( | 555 emitter.cspPrecompiledFunctionFor(outputUnit).add( |
| 549 js('#.prototype.#.${namer.reflectableField} = 1', | 556 js('#.prototype.#.${namer.reflectableField} = 1', |
| 550 [className, setterName])); | 557 [className, setterName])); |
| 551 } | 558 } |
| 552 } | 559 } |
| 553 | 560 |
| 554 void generateReflectionDataForFieldGetterOrSetter(Element member, | 561 void generateReflectionDataForFieldGetterOrSetter(Element member, |
| 555 String name, | 562 jsAst.Name name, |
| 556 ClassBuilder builder, | 563 ClassBuilder builder, |
| 557 {bool isGetter}) { | 564 {bool isGetter}) { |
| 558 Selector selector = isGetter | 565 Selector selector = isGetter |
| 559 ? new Selector.getter(member.name, member.library) | 566 ? new Selector.getter(member.name, member.library) |
| 560 : new Selector.setter(member.name, member.library); | 567 : new Selector.setter(member.name, member.library); |
| 561 String reflectionName = emitter.getReflectionName(selector, name); | 568 String reflectionName = emitter.getReflectionName(selector, name); |
| 562 if (reflectionName != null) { | 569 if (reflectionName != null) { |
| 563 var reflectable = | 570 var reflectable = |
| 564 js(backend.isAccessibleByReflection(member) ? '1' : '0'); | 571 js(backend.isAccessibleByReflection(member) ? '1' : '0'); |
| 565 builder.addProperty('+$reflectionName', reflectable); | 572 builder.addPropertyByName('+$reflectionName', reflectable); |
| 566 } | 573 } |
| 567 } | 574 } |
| 568 } | 575 } |
| OLD | NEW |