Index: lib/src/compiler/code_generator.dart |
diff --git a/lib/src/compiler/code_generator.dart b/lib/src/compiler/code_generator.dart |
index 199a629e74a9a4fbdc601c56b03680ae25dd8ca9..a45ce215ce5ed0313a5f76def2feb2a1f76eeba1 100644 |
--- a/lib/src/compiler/code_generator.dart |
+++ b/lib/src/compiler/code_generator.dart |
@@ -5,11 +5,11 @@ |
import 'dart:collection' show HashMap, HashSet; |
import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
+import 'package:analyzer/dart/ast/ast.dart' hide ConstantEvaluator; |
import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; |
import 'package:analyzer/dart/element/element.dart'; |
import 'package:analyzer/dart/element/type.dart'; |
-import 'package:analyzer/dart/ast/ast.dart' hide ConstantEvaluator; |
- |
+import 'package:analyzer/src/dart/ast/token.dart' show StringToken; |
//TODO(leafp): Remove deprecated dependency |
//ignore: DEPRECATED_MEMBER_USE |
import 'package:analyzer/src/generated/element.dart' |
@@ -17,27 +17,26 @@ import 'package:analyzer/src/generated/element.dart' |
import 'package:analyzer/src/generated/engine.dart' show AnalysisContext; |
import 'package:analyzer/src/generated/resolver.dart' |
show TypeProvider, NamespaceBuilder; |
-import 'package:analyzer/src/dart/ast/token.dart' show StringToken; |
import 'package:analyzer/src/generated/type_system.dart' |
show StrongTypeSystemImpl; |
import 'package:analyzer/src/summary/summarize_elements.dart' |
show PackageBundleAssembler; |
import 'package:analyzer/src/task/strong/info.dart' show DynamicInvoke; |
+import 'package:source_maps/source_maps.dart'; |
+import '../closure/closure_annotator.dart' show ClosureAnnotator; |
import '../js_ast/js_ast.dart' as JS; |
import '../js_ast/js_ast.dart' show js; |
-import '../closure/closure_annotator.dart' show ClosureAnnotator; |
- |
import 'ast_builder.dart' show AstBuilder; |
import 'compiler.dart' |
show BuildUnit, CompilerOptions, JSModuleFile, ModuleFormat; |
import 'element_helpers.dart'; |
import 'element_loader.dart' show ElementLoader; |
import 'extension_types.dart' show ExtensionTypeSet; |
-import 'js_field_storage.dart' show findFieldsNeedingStorage; |
+import 'js_field_storage.dart' show checkForPropertyOverride, getSuperclasses; |
import 'js_interop.dart'; |
-import 'js_names.dart' as JS; |
import 'js_metalet.dart' as JS; |
+import 'js_names.dart' as JS; |
import 'js_typeref_codegen.dart' show JsTypeRefCodegen; |
import 'module_builder.dart' |
show LegacyModuleBuilder, NodeModuleBuilder, pathToJSIdentifier; |
@@ -45,7 +44,6 @@ import 'nullable_type_inference.dart' show NullableTypeInference; |
import 'reify_coercions.dart' show CoercionReifier; |
import 'side_effect_analysis.dart' show ConstFieldVisitor, isStateless; |
import 'source_map_printer.dart' show SourceMapPrintingContext; |
-import 'package:source_maps/source_maps.dart'; |
class CodeGenerator extends GeneralizingAstVisitor |
with ClosureAnnotator, JsTypeRefCodegen, NullableTypeInference { |
@@ -69,10 +67,6 @@ class CodeGenerator extends GeneralizingAstVisitor |
/// The global extension type table. |
final ExtensionTypeSet _extensionTypes; |
- /// Information that is precomputed for this library, indicates which fields |
- /// need storage slots. |
- HashSet<FieldElement> _fieldsNeedingStorage; |
- |
/// The variable for the target of the current `..` cascade expression. |
/// |
/// Usually a [SimpleIdentifier], but it can also be other expressions |
@@ -184,9 +178,6 @@ class CodeGenerator extends GeneralizingAstVisitor |
throw new StateError('Can only call emitModule once.'); |
} |
- _fieldsNeedingStorage = findFieldsNeedingStorage( |
- compilationUnits.map((u) => u.element), _extensionTypes); |
- |
// Transform the AST to make coercions explicit. |
compilationUnits = CoercionReifier.reify(compilationUnits); |
@@ -554,7 +545,7 @@ class CodeGenerator extends GeneralizingAstVisitor |
// Emit things that come after the ES6 `class ... { ... }`. |
_setBaseClass(classElem, className, body); |
_defineNamedConstructors(ctors, body, className); |
- _emitVirtualFields(fields, className, body); |
+ _emitVirtualFields(classElem, fields, className, body); |
_emitClassSignature(methods, classElem, ctors, extensions, className, body); |
_defineExtensionMembers(extensions, className, body); |
_emitClassMetadata(node.metadata, className, body); |
@@ -774,6 +765,7 @@ class CodeGenerator extends GeneralizingAstVisitor |
} |
bool hasJsPeer = findAnnotation(element, isJsPeerInterface) != null; |
+ var superclasses = getSuperclasses(element); |
bool hasIterator = false; |
for (var m in node.members) { |
@@ -782,6 +774,10 @@ class CodeGenerator extends GeneralizingAstVisitor |
} else if (m is MethodDeclaration) { |
jsMethods.add(_emitMethodDeclaration(type, m)); |
+ if (m.element is PropertyAccessorElement) { |
+ jsMethods.add(_emitSuperAccessorWrapper(m, type, superclasses)); |
+ } |
+ |
if (!hasJsPeer && m.isGetter && m.name.name == 'iterator') { |
hasIterator = true; |
jsMethods.add(_emitIterable(type)); |
@@ -806,6 +802,32 @@ class CodeGenerator extends GeneralizingAstVisitor |
return jsMethods.where((m) => m != null).toList(growable: false); |
} |
+ JS.Method _emitSuperAccessorWrapper(MethodDeclaration method, |
+ InterfaceType type, List<ClassElement> superclasses) { |
+ var methodElement = method.element as PropertyAccessorElement; |
+ var field = methodElement.variable; |
+ if (!field.isSynthetic) return null; |
+ var propertyOverrideResult = checkForPropertyOverride( |
+ methodElement.variable, superclasses, _extensionTypes); |
+ |
+ // Generate a corresponding virtual getter / setter. |
+ var name = _elementMemberName(methodElement, |
+ allowExtensions: _extensionTypes.contains(type.element)); |
+ if (method.isGetter) { |
+ // Generate a setter |
+ if (field.setter != null || !propertyOverrideResult.foundSetter) |
+ return null; |
+ var fn = js.call('function(value) { super[#] = value; }', [name]); |
+ return new JS.Method(name, fn, isSetter: true); |
+ } else { |
+ // Generate a getter |
+ if (field.getter != null || !propertyOverrideResult.foundGetter) |
+ return null; |
+ var fn = js.call('function() { return super[#]; }', [name]); |
+ return new JS.Method(name, fn, isGetter: true); |
+ } |
+ } |
+ |
bool _implementsIterable(InterfaceType t) => |
t.interfaces.any((i) => i.element.type == types.iterableType); |
@@ -890,11 +912,18 @@ class CodeGenerator extends GeneralizingAstVisitor |
/// Emits instance fields, if they are virtual |
/// (in other words, they override a getter/setter pair). |
- void _emitVirtualFields(List<FieldDeclaration> fields, |
- JS.Expression className, List<JS.Statement> body) { |
+ void _emitVirtualFields( |
+ ClassElement classElement, |
+ List<FieldDeclaration> fields, |
+ JS.Expression className, |
+ List<JS.Statement> body) { |
+ List<ClassElement> superclasses = getSuperclasses(classElement); |
for (FieldDeclaration member in fields) { |
for (VariableDeclaration field in member.fields.variables) { |
- if (_fieldsNeedingStorage.contains(field.element)) { |
+ var propertyOverrideResult = checkForPropertyOverride( |
+ field.element, superclasses, _extensionTypes); |
+ if (propertyOverrideResult.foundGetter || |
+ propertyOverrideResult.foundSetter) { |
body.add(_overrideField(className, field.element)); |
} |
} |