| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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.program_builder; | 5 part of dart2js.js_emitter.program_builder; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * [member] is a field (instance, static, or top level). | 8 * [member] is a field (instance, static, or top level). |
| 9 * | 9 * |
| 10 * [name] is the field name that the [Namer] has picked for this field's | 10 * [name] is the field name that the [Namer] has picked for this field's |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 * If [element] is a [LibraryElement], [visitStatics] must be true. | 51 * If [element] is a [LibraryElement], [visitStatics] must be true. |
| 52 * | 52 * |
| 53 * When visiting the instance fields of a class, the fields of its superclass | 53 * When visiting the instance fields of a class, the fields of its superclass |
| 54 * are also visited if the class is instantiated. | 54 * are also visited if the class is instantiated. |
| 55 * | 55 * |
| 56 * Invariant: [element] must be a declaration element. | 56 * Invariant: [element] must be a declaration element. |
| 57 */ | 57 */ |
| 58 void visitFields(Element element, bool visitStatics, AcceptField f) { | 58 void visitFields(Element element, bool visitStatics, AcceptField f) { |
| 59 assert(invariant(element, element.isDeclaration)); | 59 assert(invariant(element, element.isDeclaration)); |
| 60 | 60 |
| 61 bool isClass = false; | 61 ClassElement cls; |
| 62 bool isNativeClass = false; |
| 62 bool isLibrary = false; | 63 bool isLibrary = false; |
| 64 bool isInstantiated = false; |
| 63 if (element.isClass) { | 65 if (element.isClass) { |
| 64 isClass = true; | 66 cls = element; |
| 67 isNativeClass = backend.nativeData.isNativeClass(cls); |
| 68 |
| 69 // If the class is never instantiated we still need to set it up for |
| 70 // inheritance purposes, but we can simplify its JavaScript constructor. |
| 71 isInstantiated = compiler.codegenWorldBuilder.directlyInstantiatedClasses |
| 72 .contains(cls); |
| 65 } else if (element.isLibrary) { | 73 } else if (element.isLibrary) { |
| 66 isLibrary = true; | 74 isLibrary = true; |
| 67 assert(invariant(element, visitStatics)); | 75 assert(invariant(element, visitStatics)); |
| 68 } else { | 76 } else { |
| 69 throw new SpannableAssertionFailure( | 77 throw new SpannableAssertionFailure( |
| 70 element, 'Expected a ClassElement or a LibraryElement.'); | 78 element, 'Expected a ClassElement or a LibraryElement.'); |
| 71 } | 79 } |
| 72 | 80 |
| 73 // If the class is never instantiated we still need to set it up for | |
| 74 // inheritance purposes, but we can simplify its JavaScript constructor. | |
| 75 bool isInstantiated = compiler | |
| 76 .codegenWorldBuilder.directlyInstantiatedClasses | |
| 77 .contains(element); | |
| 78 | |
| 79 void visitField(Element holder, FieldElement field) { | 81 void visitField(Element holder, FieldElement field) { |
| 80 assert(invariant(element, field.isDeclaration)); | 82 assert(invariant(element, field.isDeclaration)); |
| 81 | 83 |
| 82 // Keep track of whether or not we're dealing with a field mixin | 84 bool isMixinNativeField = isNativeClass && holder.isMixinApplication; |
| 83 // into a native class. | |
| 84 bool isMixinNativeField = | |
| 85 isClass && backend.isNative(element) && holder.isMixinApplication; | |
| 86 | 85 |
| 87 // See if we can dynamically create getters and setters. | 86 // See if we can dynamically create getters and setters. |
| 88 // We can only generate getters and setters for [element] since | 87 // We can only generate getters and setters for [element] since |
| 89 // the fields of super classes could be overwritten with getters or | 88 // the fields of super classes could be overwritten with getters or |
| 90 // setters. | 89 // setters. |
| 91 bool needsGetter = false; | 90 bool needsGetter = false; |
| 92 bool needsSetter = false; | 91 bool needsSetter = false; |
| 93 if (isLibrary || isMixinNativeField || holder == element) { | 92 if (isLibrary || isMixinNativeField || holder == element) { |
| 94 needsGetter = fieldNeedsGetter(field); | 93 needsGetter = fieldNeedsGetter(field); |
| 95 needsSetter = fieldNeedsSetter(field); | 94 needsSetter = fieldNeedsSetter(field); |
| 96 } | 95 } |
| 97 | 96 |
| 98 if ((isInstantiated && !backend.isNative(holder)) || | 97 if ((isInstantiated && !backend.nativeData.isNativeClass(cls)) || |
| 99 needsGetter || | 98 needsGetter || |
| 100 needsSetter) { | 99 needsSetter) { |
| 101 js.Name accessorName = namer.fieldAccessorName(field); | 100 js.Name accessorName = namer.fieldAccessorName(field); |
| 102 js.Name fieldName = namer.fieldPropertyName(field); | 101 js.Name fieldName = namer.fieldPropertyName(field); |
| 103 bool needsCheckedSetter = false; | 102 bool needsCheckedSetter = false; |
| 104 if (compiler.options.enableTypeAssertions && | 103 if (compiler.options.enableTypeAssertions && |
| 105 needsSetter && | 104 needsSetter && |
| 106 !canAvoidGeneratedCheckedSetter(field)) { | 105 !canAvoidGeneratedCheckedSetter(field)) { |
| 107 needsCheckedSetter = true; | 106 needsCheckedSetter = true; |
| 108 needsSetter = false; | 107 needsSetter = false; |
| 109 } | 108 } |
| 110 // Getters and setters with suffixes will be generated dynamically. | 109 // Getters and setters with suffixes will be generated dynamically. |
| 111 f(field, fieldName, accessorName, needsGetter, needsSetter, | 110 f(field, fieldName, accessorName, needsGetter, needsSetter, |
| 112 needsCheckedSetter); | 111 needsCheckedSetter); |
| 113 } | 112 } |
| 114 } | 113 } |
| 115 | 114 |
| 116 if (isLibrary) { | 115 if (isLibrary) { |
| 117 LibraryElement library = element; | 116 LibraryElement library = element; |
| 118 library.implementation.forEachLocalMember((Element member) { | 117 library.implementation.forEachLocalMember((Element member) { |
| 119 if (member.isField) visitField(library, member); | 118 if (member.isField) visitField(library, member); |
| 120 }); | 119 }); |
| 121 } else if (visitStatics) { | 120 } else if (visitStatics) { |
| 122 ClassElement cls = element; | |
| 123 cls.implementation.forEachStaticField(visitField); | 121 cls.implementation.forEachStaticField(visitField); |
| 124 } else { | 122 } else { |
| 125 ClassElement cls = element; | |
| 126 // TODO(kasperl): We should make sure to only emit one version of | 123 // TODO(kasperl): We should make sure to only emit one version of |
| 127 // overridden fields. Right now, we rely on the ordering so the | 124 // overridden fields. Right now, we rely on the ordering so the |
| 128 // fields pulled in from mixins are replaced with the fields from | 125 // fields pulled in from mixins are replaced with the fields from |
| 129 // the class definition. | 126 // the class definition. |
| 130 | 127 |
| 131 // If a class is not instantiated then we add the field just so we can | 128 // If a class is not instantiated then we add the field just so we can |
| 132 // generate the field getter/setter dynamically. Since this is only | 129 // generate the field getter/setter dynamically. Since this is only |
| 133 // allowed on fields that are in [element] we don't need to visit | 130 // allowed on fields that are in [element] we don't need to visit |
| 134 // superclasses for non-instantiated classes. | 131 // superclasses for non-instantiated classes. |
| 135 cls.implementation.forEachInstanceField(visitField, | 132 cls.implementation.forEachInstanceField(visitField, |
| (...skipping 27 matching lines...) Expand all Loading... |
| 163 field is ClosureFieldElement; | 160 field is ClosureFieldElement; |
| 164 } | 161 } |
| 165 | 162 |
| 166 bool canAvoidGeneratedCheckedSetter(VariableElement member) { | 163 bool canAvoidGeneratedCheckedSetter(VariableElement member) { |
| 167 // We never generate accessors for top-level/static fields. | 164 // We never generate accessors for top-level/static fields. |
| 168 if (!member.isInstanceMember) return true; | 165 if (!member.isInstanceMember) return true; |
| 169 ResolutionDartType type = member.type; | 166 ResolutionDartType type = member.type; |
| 170 return type.treatAsDynamic || type.isObject; | 167 return type.treatAsDynamic || type.isObject; |
| 171 } | 168 } |
| 172 } | 169 } |
| OLD | NEW |