| 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 * Documentation wanted -- johnniwinther | 9 * Documentation wanted -- johnniwinther |
| 10 * | 10 * |
| 11 * Invariant: [classElement] must be a declaration element. | 11 * Invariant: [classElement] must be a declaration element. |
| 12 */ | 12 */ |
| 13 void generateClass(ClassElement classElement, | 13 void generateClass(ClassElement classElement, |
| 14 ClassBuilder properties, | 14 ClassBuilder properties, |
| 15 Map<String, jsAst.Expression> additionalProperties) { | 15 Map<String, jsAst.Expression> additionalProperties) { |
| 16 final onlyForRti = | 16 final onlyForRti = |
| 17 task.typeTestEmitter.rtiNeededClasses.contains(classElement); | 17 task.typeTestEmitter.rtiNeededClasses.contains(classElement); |
| 18 | 18 |
| 19 assert(invariant(classElement, classElement.isDeclaration)); | 19 assert(invariant(classElement, classElement.isDeclaration)); |
| 20 assert(invariant(classElement, !classElement.isNative() || onlyForRti)); | 20 assert(invariant(classElement, !classElement.isNative || onlyForRti)); |
| 21 | 21 |
| 22 task.needsDefineClass = true; | 22 task.needsDefineClass = true; |
| 23 String className = namer.getNameOfClass(classElement); | 23 String className = namer.getNameOfClass(classElement); |
| 24 | 24 |
| 25 ClassElement superclass = classElement.superclass; | 25 ClassElement superclass = classElement.superclass; |
| 26 String superName = ""; | 26 String superName = ""; |
| 27 if (superclass != null) { | 27 if (superclass != null) { |
| 28 superName = namer.getNameOfClass(superclass); | 28 superName = namer.getNameOfClass(superclass); |
| 29 } | 29 } |
| 30 | 30 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 55 emitTypeVariableReaders(classElement, builder); | 55 emitTypeVariableReaders(classElement, builder); |
| 56 | 56 |
| 57 emitClassBuilderWithReflectionData( | 57 emitClassBuilderWithReflectionData( |
| 58 className, classElement, builder, properties); | 58 className, classElement, builder, properties); |
| 59 } | 59 } |
| 60 | 60 |
| 61 void emitClassConstructor(ClassElement classElement, | 61 void emitClassConstructor(ClassElement classElement, |
| 62 ClassBuilder builder, | 62 ClassBuilder builder, |
| 63 {bool onlyForRti: false}) { | 63 {bool onlyForRti: false}) { |
| 64 List<String> fields = <String>[]; | 64 List<String> fields = <String>[]; |
| 65 if (!onlyForRti && !classElement.isNative()) { | 65 if (!onlyForRti && !classElement.isNative) { |
| 66 visitFields(classElement, false, | 66 visitFields(classElement, false, |
| 67 (Element member, | 67 (Element member, |
| 68 String name, | 68 String name, |
| 69 String accessorName, | 69 String accessorName, |
| 70 bool needsGetter, | 70 bool needsGetter, |
| 71 bool needsSetter, | 71 bool needsSetter, |
| 72 bool needsCheckedSetter) { | 72 bool needsCheckedSetter) { |
| 73 fields.add(name); | 73 fields.add(name); |
| 74 }); | 74 }); |
| 75 } | 75 } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 } | 109 } |
| 110 | 110 |
| 111 /// Returns `true` if fields added. | 111 /// Returns `true` if fields added. |
| 112 bool emitFields(Element element, | 112 bool emitFields(Element element, |
| 113 ClassBuilder builder, | 113 ClassBuilder builder, |
| 114 String superName, | 114 String superName, |
| 115 { bool classIsNative: false, | 115 { bool classIsNative: false, |
| 116 bool emitStatics: false, | 116 bool emitStatics: false, |
| 117 bool onlyForRti: false }) { | 117 bool onlyForRti: false }) { |
| 118 assert(!emitStatics || !onlyForRti); | 118 assert(!emitStatics || !onlyForRti); |
| 119 if (element.isLibrary()) { | 119 if (element.isLibrary) { |
| 120 assert(invariant(element, emitStatics)); | 120 assert(invariant(element, emitStatics)); |
| 121 } else if (!element.isClass()) { | 121 } else if (!element.isClass) { |
| 122 throw new SpannableAssertionFailure( | 122 throw new SpannableAssertionFailure( |
| 123 element, 'Must be a ClassElement or a LibraryElement'); | 123 element, 'Must be a ClassElement or a LibraryElement'); |
| 124 } | 124 } |
| 125 if (emitStatics) { | 125 if (emitStatics) { |
| 126 assert(invariant(element, superName == null, message: superName)); | 126 assert(invariant(element, superName == null, message: superName)); |
| 127 } else { | 127 } else { |
| 128 assert(invariant(element, superName != null)); | 128 assert(invariant(element, superName != null)); |
| 129 builder.superName = superName; | 129 builder.superName = superName; |
| 130 } | 130 } |
| 131 var fieldMetadata = []; | 131 var fieldMetadata = []; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 171 int getterCode = 0; | 171 int getterCode = 0; |
| 172 if (needsAccessor && backend.fieldHasInterceptedGetter(field)) { | 172 if (needsAccessor && backend.fieldHasInterceptedGetter(field)) { |
| 173 task.interceptorEmitter.interceptorInvocationNames.add( | 173 task.interceptorEmitter.interceptorInvocationNames.add( |
| 174 namer.getterName(field)); | 174 namer.getterName(field)); |
| 175 } | 175 } |
| 176 if (needsAccessor && backend.fieldHasInterceptedGetter(field)) { | 176 if (needsAccessor && backend.fieldHasInterceptedGetter(field)) { |
| 177 task.interceptorEmitter.interceptorInvocationNames.add( | 177 task.interceptorEmitter.interceptorInvocationNames.add( |
| 178 namer.setterName(field)); | 178 namer.setterName(field)); |
| 179 } | 179 } |
| 180 if (needsGetter) { | 180 if (needsGetter) { |
| 181 if (field.isInstanceMember()) { | 181 if (field.isInstanceMember) { |
| 182 // 01: function() { return this.field; } | 182 // 01: function() { return this.field; } |
| 183 // 10: function(receiver) { return receiver.field; } | 183 // 10: function(receiver) { return receiver.field; } |
| 184 // 11: function(receiver) { return this.field; } | 184 // 11: function(receiver) { return this.field; } |
| 185 bool isIntercepted = backend.fieldHasInterceptedGetter(field); | 185 bool isIntercepted = backend.fieldHasInterceptedGetter(field); |
| 186 getterCode += isIntercepted ? 2 : 0; | 186 getterCode += isIntercepted ? 2 : 0; |
| 187 getterCode += backend.isInterceptorClass(element) ? 0 : 1; | 187 getterCode += backend.isInterceptorClass(element) ? 0 : 1; |
| 188 // TODO(sra): 'isInterceptorClass' might not be the correct test | 188 // TODO(sra): 'isInterceptorClass' might not be the correct test |
| 189 // for methods forced to use the interceptor convention because | 189 // for methods forced to use the interceptor convention because |
| 190 // the method's class was elsewhere mixed-in to an interceptor. | 190 // the method's class was elsewhere mixed-in to an interceptor. |
| 191 assert(!field.isInstanceMember() || getterCode != 0); | 191 assert(!field.isInstanceMember || getterCode != 0); |
| 192 if (isIntercepted) { | 192 if (isIntercepted) { |
| 193 task.interceptorEmitter.interceptorInvocationNames.add( | 193 task.interceptorEmitter.interceptorInvocationNames.add( |
| 194 namer.getterName(field)); | 194 namer.getterName(field)); |
| 195 } | 195 } |
| 196 } else { | 196 } else { |
| 197 getterCode = 1; | 197 getterCode = 1; |
| 198 } | 198 } |
| 199 } | 199 } |
| 200 int setterCode = 0; | 200 int setterCode = 0; |
| 201 if (needsSetter) { | 201 if (needsSetter) { |
| 202 if (field.isInstanceMember()) { | 202 if (field.isInstanceMember) { |
| 203 // 01: function(value) { this.field = value; } | 203 // 01: function(value) { this.field = value; } |
| 204 // 10: function(receiver, value) { receiver.field = value; } | 204 // 10: function(receiver, value) { receiver.field = value; } |
| 205 // 11: function(receiver, value) { this.field = value; } | 205 // 11: function(receiver, value) { this.field = value; } |
| 206 bool isIntercepted = backend.fieldHasInterceptedSetter(field); | 206 bool isIntercepted = backend.fieldHasInterceptedSetter(field); |
| 207 setterCode += isIntercepted ? 2 : 0; | 207 setterCode += isIntercepted ? 2 : 0; |
| 208 setterCode += backend.isInterceptorClass(element) ? 0 : 1; | 208 setterCode += backend.isInterceptorClass(element) ? 0 : 1; |
| 209 assert(!field.isInstanceMember() || setterCode != 0); | 209 assert(!field.isInstanceMember || setterCode != 0); |
| 210 if (isIntercepted) { | 210 if (isIntercepted) { |
| 211 task.interceptorEmitter.interceptorInvocationNames.add( | 211 task.interceptorEmitter.interceptorInvocationNames.add( |
| 212 namer.setterName(field)); | 212 namer.setterName(field)); |
| 213 } | 213 } |
| 214 } else { | 214 } else { |
| 215 setterCode = 1; | 215 setterCode = 1; |
| 216 } | 216 } |
| 217 } | 217 } |
| 218 int code = getterCode + (setterCode << 2); | 218 int code = getterCode + (setterCode << 2); |
| 219 if (code == 0) { | 219 if (code == 0) { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 276 */ | 276 */ |
| 277 void emitInstanceMembers(ClassElement classElement, | 277 void emitInstanceMembers(ClassElement classElement, |
| 278 ClassBuilder builder, | 278 ClassBuilder builder, |
| 279 {bool onlyForRti: false}) { | 279 {bool onlyForRti: false}) { |
| 280 assert(invariant(classElement, classElement.isDeclaration)); | 280 assert(invariant(classElement, classElement.isDeclaration)); |
| 281 | 281 |
| 282 if (onlyForRti || classElement.isMixinApplication) return; | 282 if (onlyForRti || classElement.isMixinApplication) return; |
| 283 | 283 |
| 284 void visitMember(ClassElement enclosing, Element member) { | 284 void visitMember(ClassElement enclosing, Element member) { |
| 285 assert(invariant(classElement, member.isDeclaration)); | 285 assert(invariant(classElement, member.isDeclaration)); |
| 286 if (member.isInstanceMember()) { | 286 if (member.isInstanceMember) { |
| 287 task.containerBuilder.addMember(member, builder); | 287 task.containerBuilder.addMember(member, builder); |
| 288 } | 288 } |
| 289 } | 289 } |
| 290 | 290 |
| 291 classElement.implementation.forEachMember( | 291 classElement.implementation.forEachMember( |
| 292 visitMember, | 292 visitMember, |
| 293 includeBackendMembers: true); | 293 includeBackendMembers: true); |
| 294 | 294 |
| 295 if (identical(classElement, compiler.objectClass) | 295 if (identical(classElement, compiler.objectClass) |
| 296 && compiler.enabledNoSuchMethod) { | 296 && compiler.enabledNoSuchMethod) { |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 383 * When visiting the instance fields of a class, the fields of its superclass | 383 * When visiting the instance fields of a class, the fields of its superclass |
| 384 * are also visited if the class is instantiated. | 384 * are also visited if the class is instantiated. |
| 385 * | 385 * |
| 386 * Invariant: [element] must be a declaration element. | 386 * Invariant: [element] must be a declaration element. |
| 387 */ | 387 */ |
| 388 void visitFields(Element element, bool visitStatics, AcceptField f) { | 388 void visitFields(Element element, bool visitStatics, AcceptField f) { |
| 389 assert(invariant(element, element.isDeclaration)); | 389 assert(invariant(element, element.isDeclaration)); |
| 390 | 390 |
| 391 bool isClass = false; | 391 bool isClass = false; |
| 392 bool isLibrary = false; | 392 bool isLibrary = false; |
| 393 if (element.isClass()) { | 393 if (element.isClass) { |
| 394 isClass = true; | 394 isClass = true; |
| 395 } else if (element.isLibrary()) { | 395 } else if (element.isLibrary) { |
| 396 isLibrary = true; | 396 isLibrary = true; |
| 397 assert(invariant(element, visitStatics)); | 397 assert(invariant(element, visitStatics)); |
| 398 } else { | 398 } else { |
| 399 throw new SpannableAssertionFailure( | 399 throw new SpannableAssertionFailure( |
| 400 element, 'Expected a ClassElement or a LibraryElement.'); | 400 element, 'Expected a ClassElement or a LibraryElement.'); |
| 401 } | 401 } |
| 402 | 402 |
| 403 // If the class is never instantiated we still need to set it up for | 403 // If the class is never instantiated we still need to set it up for |
| 404 // inheritance purposes, but we can simplify its JavaScript constructor. | 404 // inheritance purposes, but we can simplify its JavaScript constructor. |
| 405 bool isInstantiated = | 405 bool isInstantiated = |
| 406 compiler.codegenWorld.instantiatedClasses.contains(element); | 406 compiler.codegenWorld.instantiatedClasses.contains(element); |
| 407 | 407 |
| 408 void visitField(Element holder, VariableElement field) { | 408 void visitField(Element holder, VariableElement field) { |
| 409 assert(invariant(element, field.isDeclaration)); | 409 assert(invariant(element, field.isDeclaration)); |
| 410 String name = field.name; | 410 String name = field.name; |
| 411 | 411 |
| 412 // Keep track of whether or not we're dealing with a field mixin | 412 // Keep track of whether or not we're dealing with a field mixin |
| 413 // into a native class. | 413 // into a native class. |
| 414 bool isMixinNativeField = | 414 bool isMixinNativeField = |
| 415 isClass && element.isNative() && holder.isMixinApplication; | 415 isClass && element.isNative && holder.isMixinApplication; |
| 416 | 416 |
| 417 // See if we can dynamically create getters and setters. | 417 // See if we can dynamically create getters and setters. |
| 418 // We can only generate getters and setters for [element] since | 418 // We can only generate getters and setters for [element] since |
| 419 // the fields of super classes could be overwritten with getters or | 419 // the fields of super classes could be overwritten with getters or |
| 420 // setters. | 420 // setters. |
| 421 bool needsGetter = false; | 421 bool needsGetter = false; |
| 422 bool needsSetter = false; | 422 bool needsSetter = false; |
| 423 if (isLibrary || isMixinNativeField || holder == element) { | 423 if (isLibrary || isMixinNativeField || holder == element) { |
| 424 needsGetter = fieldNeedsGetter(field); | 424 needsGetter = fieldNeedsGetter(field); |
| 425 needsSetter = fieldNeedsSetter(field); | 425 needsSetter = fieldNeedsSetter(field); |
| 426 } | 426 } |
| 427 | 427 |
| 428 if ((isInstantiated && !holder.isNative()) | 428 if ((isInstantiated && !holder.isNative) |
| 429 || needsGetter | 429 || needsGetter |
| 430 || needsSetter) { | 430 || needsSetter) { |
| 431 String accessorName = namer.fieldAccessorName(field); | 431 String accessorName = namer.fieldAccessorName(field); |
| 432 String fieldName = namer.fieldPropertyName(field); | 432 String fieldName = namer.fieldPropertyName(field); |
| 433 bool needsCheckedSetter = false; | 433 bool needsCheckedSetter = false; |
| 434 if (compiler.enableTypeAssertions | 434 if (compiler.enableTypeAssertions |
| 435 && needsSetter | 435 && needsSetter |
| 436 && !canAvoidGeneratedCheckedSetter(field)) { | 436 && !canAvoidGeneratedCheckedSetter(field)) { |
| 437 needsCheckedSetter = true; | 437 needsCheckedSetter = true; |
| 438 needsSetter = false; | 438 needsSetter = false; |
| 439 } | 439 } |
| 440 // Getters and setters with suffixes will be generated dynamically. | 440 // Getters and setters with suffixes will be generated dynamically. |
| 441 f(field, fieldName, accessorName, needsGetter, needsSetter, | 441 f(field, fieldName, accessorName, needsGetter, needsSetter, |
| 442 needsCheckedSetter); | 442 needsCheckedSetter); |
| 443 } | 443 } |
| 444 } | 444 } |
| 445 | 445 |
| 446 if (isLibrary) { | 446 if (isLibrary) { |
| 447 LibraryElement library = element; | 447 LibraryElement library = element; |
| 448 library.implementation.forEachLocalMember((Element member) { | 448 library.implementation.forEachLocalMember((Element member) { |
| 449 if (member.isField()) visitField(library, member); | 449 if (member.isField) visitField(library, member); |
| 450 }); | 450 }); |
| 451 } else if (visitStatics) { | 451 } else if (visitStatics) { |
| 452 ClassElement cls = element; | 452 ClassElement cls = element; |
| 453 cls.implementation.forEachStaticField(visitField); | 453 cls.implementation.forEachStaticField(visitField); |
| 454 } else { | 454 } else { |
| 455 ClassElement cls = element; | 455 ClassElement cls = element; |
| 456 // TODO(kasperl): We should make sure to only emit one version of | 456 // TODO(kasperl): We should make sure to only emit one version of |
| 457 // overridden fields. Right now, we rely on the ordering so the | 457 // overridden fields. Right now, we rely on the ordering so the |
| 458 // fields pulled in from mixins are replaced with the fields from | 458 // fields pulled in from mixins are replaced with the fields from |
| 459 // the class definition. | 459 // the class definition. |
| 460 | 460 |
| 461 // If a class is not instantiated then we add the field just so we can | 461 // If a class is not instantiated then we add the field just so we can |
| 462 // generate the field getter/setter dynamically. Since this is only | 462 // generate the field getter/setter dynamically. Since this is only |
| 463 // allowed on fields that are in [element] we don't need to visit | 463 // allowed on fields that are in [element] we don't need to visit |
| 464 // superclasses for non-instantiated classes. | 464 // superclasses for non-instantiated classes. |
| 465 cls.implementation.forEachInstanceField( | 465 cls.implementation.forEachInstanceField( |
| 466 visitField, includeSuperAndInjectedMembers: isInstantiated); | 466 visitField, includeSuperAndInjectedMembers: isInstantiated); |
| 467 } | 467 } |
| 468 } | 468 } |
| 469 | 469 |
| 470 void recordMangledField(Element member, | 470 void recordMangledField(Element member, |
| 471 String accessorName, | 471 String accessorName, |
| 472 String memberName) { | 472 String memberName) { |
| 473 if (!backend.shouldRetainGetter(member)) return; | 473 if (!backend.shouldRetainGetter(member)) return; |
| 474 String previousName; | 474 String previousName; |
| 475 if (member.isInstanceMember()) { | 475 if (member.isInstanceMember) { |
| 476 previousName = task.mangledFieldNames.putIfAbsent( | 476 previousName = task.mangledFieldNames.putIfAbsent( |
| 477 '${namer.getterPrefix}$accessorName', | 477 '${namer.getterPrefix}$accessorName', |
| 478 () => memberName); | 478 () => memberName); |
| 479 } else { | 479 } else { |
| 480 previousName = task.mangledGlobalFieldNames.putIfAbsent( | 480 previousName = task.mangledGlobalFieldNames.putIfAbsent( |
| 481 accessorName, | 481 accessorName, |
| 482 () => memberName); | 482 () => memberName); |
| 483 } | 483 } |
| 484 assert(invariant(member, previousName == memberName, | 484 assert(invariant(member, previousName == memberName, |
| 485 message: '$previousName != ${memberName}')); | 485 message: '$previousName != ${memberName}')); |
| 486 } | 486 } |
| 487 | 487 |
| 488 bool fieldNeedsGetter(VariableElement field) { | 488 bool fieldNeedsGetter(VariableElement field) { |
| 489 assert(field.isField()); | 489 assert(field.isField); |
| 490 if (fieldAccessNeverThrows(field)) return false; | 490 if (fieldAccessNeverThrows(field)) return false; |
| 491 return backend.shouldRetainGetter(field) | 491 return backend.shouldRetainGetter(field) |
| 492 || compiler.codegenWorld.hasInvokedGetter(field, compiler); | 492 || compiler.codegenWorld.hasInvokedGetter(field, compiler); |
| 493 } | 493 } |
| 494 | 494 |
| 495 bool fieldNeedsSetter(VariableElement field) { | 495 bool fieldNeedsSetter(VariableElement field) { |
| 496 assert(field.isField()); | 496 assert(field.isField); |
| 497 if (fieldAccessNeverThrows(field)) return false; | 497 if (fieldAccessNeverThrows(field)) return false; |
| 498 return (!field.modifiers.isFinalOrConst()) | 498 return (!field.modifiers.isFinalOrConst) |
| 499 && (backend.shouldRetainSetter(field) | 499 && (backend.shouldRetainSetter(field) |
| 500 || compiler.codegenWorld.hasInvokedSetter(field, compiler)); | 500 || compiler.codegenWorld.hasInvokedSetter(field, compiler)); |
| 501 } | 501 } |
| 502 | 502 |
| 503 // We never access a field in a closure (a captured variable) without knowing | 503 // We never access a field in a closure (a captured variable) without knowing |
| 504 // that it is there. Therefore we don't need to use a getter (that will throw | 504 // that it is there. Therefore we don't need to use a getter (that will throw |
| 505 // if the getter method is missing), but can always access the field directly. | 505 // if the getter method is missing), but can always access the field directly. |
| 506 static bool fieldAccessNeverThrows(VariableElement field) { | 506 static bool fieldAccessNeverThrows(VariableElement field) { |
| 507 return field is ClosureFieldElement; | 507 return field is ClosureFieldElement; |
| 508 } | 508 } |
| 509 | 509 |
| 510 bool canAvoidGeneratedCheckedSetter(VariableElement member) { | 510 bool canAvoidGeneratedCheckedSetter(VariableElement member) { |
| 511 // We never generate accessors for top-level/static fields. | 511 // We never generate accessors for top-level/static fields. |
| 512 if (!member.isInstanceMember()) return true; | 512 if (!member.isInstanceMember) return true; |
| 513 DartType type = member.type; | 513 DartType type = member.type; |
| 514 return type.treatAsDynamic || (type.element == compiler.objectClass); | 514 return type.treatAsDynamic || (type.element == compiler.objectClass); |
| 515 } | 515 } |
| 516 | 516 |
| 517 void generateCheckedSetter(Element member, | 517 void generateCheckedSetter(Element member, |
| 518 String fieldName, | 518 String fieldName, |
| 519 String accessorName, | 519 String accessorName, |
| 520 ClassBuilder builder) { | 520 ClassBuilder builder) { |
| 521 jsAst.Expression code = backend.generatedCode[member]; | 521 jsAst.Expression code = backend.generatedCode[member]; |
| 522 assert(code != null); | 522 assert(code != null); |
| 523 String setterName = namer.setterNameFromAccessorName(accessorName); | 523 String setterName = namer.setterNameFromAccessorName(accessorName); |
| 524 builder.addProperty(setterName, code); | 524 builder.addProperty(setterName, code); |
| 525 generateReflectionDataForFieldGetterOrSetter( | 525 generateReflectionDataForFieldGetterOrSetter( |
| 526 member, setterName, builder, isGetter: false); | 526 member, setterName, builder, isGetter: false); |
| 527 } | 527 } |
| 528 | 528 |
| 529 void generateGetter(Element member, String fieldName, String accessorName, | 529 void generateGetter(Element member, String fieldName, String accessorName, |
| 530 ClassBuilder builder) { | 530 ClassBuilder builder) { |
| 531 String getterName = namer.getterNameFromAccessorName(accessorName); | 531 String getterName = namer.getterNameFromAccessorName(accessorName); |
| 532 ClassElement cls = member.getEnclosingClass(); | 532 ClassElement cls = member.enclosingClass; |
| 533 String className = namer.getNameOfClass(cls); | 533 String className = namer.getNameOfClass(cls); |
| 534 String receiver = backend.isInterceptorClass(cls) ? 'receiver' : 'this'; | 534 String receiver = backend.isInterceptorClass(cls) ? 'receiver' : 'this'; |
| 535 List<String> args = backend.isInterceptedMethod(member) ? ['receiver'] : []; | 535 List<String> args = backend.isInterceptedMethod(member) ? ['receiver'] : []; |
| 536 task.precompiledFunction.add( | 536 task.precompiledFunction.add( |
| 537 js('#.prototype.# = function(#) { return #.# }', | 537 js('#.prototype.# = function(#) { return #.# }', |
| 538 [className, getterName, args, receiver, fieldName])); | 538 [className, getterName, args, receiver, fieldName])); |
| 539 if (backend.isNeededForReflection(member)) { | 539 if (backend.isNeededForReflection(member)) { |
| 540 task.precompiledFunction.add( | 540 task.precompiledFunction.add( |
| 541 js('#.prototype.#.${namer.reflectableField} = 1', | 541 js('#.prototype.#.${namer.reflectableField} = 1', |
| 542 [className, getterName])); | 542 [className, getterName])); |
| 543 } | 543 } |
| 544 } | 544 } |
| 545 | 545 |
| 546 void generateSetter(Element member, String fieldName, String accessorName, | 546 void generateSetter(Element member, String fieldName, String accessorName, |
| 547 ClassBuilder builder) { | 547 ClassBuilder builder) { |
| 548 String setterName = namer.setterNameFromAccessorName(accessorName); | 548 String setterName = namer.setterNameFromAccessorName(accessorName); |
| 549 ClassElement cls = member.getEnclosingClass(); | 549 ClassElement cls = member.enclosingClass; |
| 550 String className = namer.getNameOfClass(cls); | 550 String className = namer.getNameOfClass(cls); |
| 551 String receiver = backend.isInterceptorClass(cls) ? 'receiver' : 'this'; | 551 String receiver = backend.isInterceptorClass(cls) ? 'receiver' : 'this'; |
| 552 List<String> args = backend.isInterceptedMethod(member) ? ['receiver'] : []; | 552 List<String> args = backend.isInterceptedMethod(member) ? ['receiver'] : []; |
| 553 task.precompiledFunction.add( | 553 task.precompiledFunction.add( |
| 554 // TODO: remove 'return'? | 554 // TODO: remove 'return'? |
| 555 js('#.prototype.# = function(#, v) { return #.# = v; }', | 555 js('#.prototype.# = function(#, v) { return #.# = v; }', |
| 556 [className, setterName, args, receiver, fieldName])); | 556 [className, setterName, args, receiver, fieldName])); |
| 557 if (backend.isNeededForReflection(member)) { | 557 if (backend.isNeededForReflection(member)) { |
| 558 task.precompiledFunction.add( | 558 task.precompiledFunction.add( |
| 559 js('#.prototype.#.${namer.reflectableField} = 1', | 559 js('#.prototype.#.${namer.reflectableField} = 1', |
| 560 [className, setterName])); | 560 [className, setterName])); |
| 561 } | 561 } |
| 562 } | 562 } |
| 563 | 563 |
| 564 void generateReflectionDataForFieldGetterOrSetter(Element member, | 564 void generateReflectionDataForFieldGetterOrSetter(Element member, |
| 565 String name, | 565 String name, |
| 566 ClassBuilder builder, | 566 ClassBuilder builder, |
| 567 {bool isGetter}) { | 567 {bool isGetter}) { |
| 568 Selector selector = isGetter | 568 Selector selector = isGetter |
| 569 ? new Selector.getter(member.name, member.getLibrary()) | 569 ? new Selector.getter(member.name, member.library) |
| 570 : new Selector.setter(member.name, member.getLibrary()); | 570 : new Selector.setter(member.name, member.library); |
| 571 String reflectionName = task.getReflectionName(selector, name); | 571 String reflectionName = task.getReflectionName(selector, name); |
| 572 if (reflectionName != null) { | 572 if (reflectionName != null) { |
| 573 var reflectable = | 573 var reflectable = |
| 574 js(backend.isAccessibleByReflection(member) ? '1' : '0'); | 574 js(backend.isAccessibleByReflection(member) ? '1' : '0'); |
| 575 builder.addProperty('+$reflectionName', reflectable); | 575 builder.addProperty('+$reflectionName', reflectable); |
| 576 } | 576 } |
| 577 } | 577 } |
| 578 | 578 |
| 579 void emitTypeVariableReaders(ClassElement cls, ClassBuilder builder) { | 579 void emitTypeVariableReaders(ClassElement cls, ClassBuilder builder) { |
| 580 List typeVariables = []; | 580 List typeVariables = []; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 610 computeTypeVariable = | 610 computeTypeVariable = |
| 611 js(r'this.$builtinTypeInfo && this.$builtinTypeInfo[#]', index); | 611 js(r'this.$builtinTypeInfo && this.$builtinTypeInfo[#]', index); |
| 612 } | 612 } |
| 613 jsAst.Expression convertRtiToRuntimeType = | 613 jsAst.Expression convertRtiToRuntimeType = |
| 614 namer.elementAccess(compiler.findHelper('convertRtiToRuntimeType')); | 614 namer.elementAccess(compiler.findHelper('convertRtiToRuntimeType')); |
| 615 builder.addProperty(name, | 615 builder.addProperty(name, |
| 616 js('function () { return #(#) }', | 616 js('function () { return #(#) }', |
| 617 [convertRtiToRuntimeType, computeTypeVariable])); | 617 [convertRtiToRuntimeType, computeTypeVariable])); |
| 618 } | 618 } |
| 619 } | 619 } |
| OLD | NEW |