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 | 2 |
3 // for details. All rights reserved. Use of this source code is governed by a | 3 // for details. All rights reserved. Use of this source code is governed by a |
4 // BSD-style license that can be found in the LICENSE file. | 4 // BSD-style license that can be found in the LICENSE file. |
5 | 5 |
6 import 'dart:collection' show HashMap, HashSet; | 6 import 'dart:collection' show HashMap, HashSet; |
7 import 'dart:math' show min, max; | 7 import 'dart:math' show min, max; |
8 | 8 |
9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
10 import 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 | 92 |
93 /// In an async* function, this represents the stream controller parameter. | 93 /// In an async* function, this represents the stream controller parameter. |
94 JS.TemporaryId _asyncStarController; | 94 JS.TemporaryId _asyncStarController; |
95 | 95 |
96 // TODO(jmesserly): fuse this with notNull check. | 96 // TODO(jmesserly): fuse this with notNull check. |
97 final _privateNames = | 97 final _privateNames = |
98 new HashMap<LibraryElement, HashMap<String, JS.TemporaryId>>(); | 98 new HashMap<LibraryElement, HashMap<String, JS.TemporaryId>>(); |
99 final _initializingFormalTemps = | 99 final _initializingFormalTemps = |
100 new HashMap<ParameterElement, JS.TemporaryId>(); | 100 new HashMap<ParameterElement, JS.TemporaryId>(); |
101 | 101 |
| 102 final _syntheticSuperclasses = new HashMap<ClassElement, JS.Identifier>(); |
| 103 |
102 JS.Identifier _extensionSymbolsModule; | 104 JS.Identifier _extensionSymbolsModule; |
103 JS.Identifier _runtimeModule; | 105 JS.Identifier _runtimeModule; |
104 final namedArgumentTemp = new JS.TemporaryId('opts'); | 106 final namedArgumentTemp = new JS.TemporaryId('opts'); |
105 | 107 |
106 final _hasDeferredSupertype = new HashSet<ClassElement>(); | 108 final _hasDeferredSupertype = new HashSet<ClassElement>(); |
107 | 109 |
108 final _eagerTopLevelFields = new HashSet<Element>.identity(); | 110 final _eagerTopLevelFields = new HashSet<Element>.identity(); |
109 | 111 |
110 /// The type provider from the current Analysis [context]. | 112 /// The type provider from the current Analysis [context]. |
111 final TypeProvider types; | 113 final TypeProvider types; |
(...skipping 702 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
814 _classProperties = new ClassPropertyModel.build(classElem, extensions); | 816 _classProperties = new ClassPropertyModel.build(classElem, extensions); |
815 | 817 |
816 var classExpr = _emitClassExpression( | 818 var classExpr = _emitClassExpression( |
817 classElem, _emitClassMethods(node, ctors, fields), | 819 classElem, _emitClassMethods(node, ctors, fields), |
818 fields: allFields); | 820 fields: allFields); |
819 | 821 |
820 var body = <JS.Statement>[]; | 822 var body = <JS.Statement>[]; |
821 _initExtensionSymbols(classElem, methods, fields, body); | 823 _initExtensionSymbols(classElem, methods, fields, body); |
822 _emitSuperHelperSymbols(_superHelperSymbols, body); | 824 _emitSuperHelperSymbols(_superHelperSymbols, body); |
823 | 825 |
| 826 var syntheticSuperId = _syntheticSuperclasses[classElem]; |
| 827 if (syntheticSuperId != null) { |
| 828 body.add(js.statement('const # = #;', [ |
| 829 syntheticSuperId, |
| 830 _emitSyntheticSuperClassExpr(classElem, syntheticSuperId) |
| 831 ])); |
| 832 } |
| 833 |
824 // Emit the class, e.g. `core.Object = class Object { ... }` | 834 // Emit the class, e.g. `core.Object = class Object { ... }` |
825 _defineClass(classElem, className, classExpr, isCallable, body); | 835 _defineClass(classElem, className, classExpr, isCallable, body); |
826 | 836 |
827 // Emit things that come after the ES6 `class ... { ... }`. | 837 // Emit things that come after the ES6 `class ... { ... }`. |
828 var jsPeerNames = _getJSPeerNames(classElem); | 838 var jsPeerNames = _getJSPeerNames(classElem); |
| 839 var targetClassName = syntheticSuperId ?? className; |
829 JS.Statement deferredBaseClass = | 840 JS.Statement deferredBaseClass = |
830 _setBaseClass(classElem, className, jsPeerNames, body); | 841 _setBaseClass(classElem, targetClassName, className, jsPeerNames, body); |
831 | 842 |
832 _emitClassTypeTests(classElem, className, body); | 843 _emitClassTypeTests(classElem, className, body); |
833 | 844 |
834 _defineNamedConstructors(ctors, body, className, isCallableTransitive); | 845 _defineNamedConstructors(ctors, body, className, isCallableTransitive); |
835 _emitVirtualFieldSymbols(className, body); | 846 _emitVirtualFieldSymbols(className, body); |
| 847 _emitVirtualizedFieldSymbols(className, body); |
836 _emitClassSignature( | 848 _emitClassSignature( |
837 methods, allFields, classElem, ctors, extensions, className, body); | 849 methods, allFields, classElem, ctors, extensions, className, body); |
838 _defineExtensionMembers(extensions, className, body); | 850 _defineExtensionMembers(extensions, className, body); |
839 _emitClassMetadata(node.metadata, className, body); | 851 _emitClassMetadata(node.metadata, className, body); |
840 | 852 |
841 JS.Statement classDef = _statement(body); | 853 JS.Statement classDef = _statement(body); |
842 | 854 |
843 var typeFormals = classElem.typeParameters; | 855 var typeFormals = classElem.typeParameters; |
844 if (typeFormals.isNotEmpty) { | 856 if (typeFormals.isNotEmpty) { |
845 classDef = _defineClassTypeArguments( | 857 classDef = _defineClassTypeArguments( |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1090 } | 1102 } |
1091 | 1103 |
1092 void _emitVirtualFieldSymbols( | 1104 void _emitVirtualFieldSymbols( |
1093 JS.Expression className, List<JS.Statement> body) { | 1105 JS.Expression className, List<JS.Statement> body) { |
1094 _classProperties.virtualFields.forEach((field, virtualField) { | 1106 _classProperties.virtualFields.forEach((field, virtualField) { |
1095 body.add(js.statement('const # = Symbol(#.name + "." + #.toString());', | 1107 body.add(js.statement('const # = Symbol(#.name + "." + #.toString());', |
1096 [virtualField, className, _declareMemberName(field.getter)])); | 1108 [virtualField, className, _declareMemberName(field.getter)])); |
1097 }); | 1109 }); |
1098 } | 1110 } |
1099 | 1111 |
| 1112 void _emitVirtualizedFieldSymbols( |
| 1113 JS.Expression className, List<JS.Statement> body) { |
| 1114 _classProperties.virtualizedFields.forEach((field, virtualField) { |
| 1115 body.add(js.statement('const # = #;', [ |
| 1116 virtualField, |
| 1117 _callHelper('virtualName(#)', _declareMemberName(field.getter)) |
| 1118 ])); |
| 1119 }); |
| 1120 } |
| 1121 |
1100 void _defineClass(ClassElement classElem, JS.Expression className, | 1122 void _defineClass(ClassElement classElem, JS.Expression className, |
1101 JS.ClassExpression classExpr, bool isCallable, List<JS.Statement> body) { | 1123 JS.ClassExpression classExpr, bool isCallable, List<JS.Statement> body) { |
1102 JS.Expression callableClass; | 1124 JS.Expression callableClass; |
1103 if (isCallable && classElem.unnamedConstructor != null) { | 1125 if (isCallable && classElem.unnamedConstructor != null) { |
1104 callableClass = | 1126 callableClass = |
1105 _emitCallableClass(classExpr, classElem.unnamedConstructor); | 1127 _emitCallableClass(classExpr, classElem.unnamedConstructor); |
1106 } | 1128 } |
1107 | 1129 |
1108 if (classElem.typeParameters.isNotEmpty) { | 1130 if (classElem.typeParameters.isNotEmpty) { |
1109 if (callableClass != null) { | 1131 if (callableClass != null) { |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1227 var genericInst = _emitType(dynType, lowerGeneric: true); | 1249 var genericInst = _emitType(dynType, lowerGeneric: true); |
1228 return js.statement( | 1250 return js.statement( |
1229 '{ #; # = #; }', [genericDef, _emitTopLevelName(element), genericInst]); | 1251 '{ #; # = #; }', [genericDef, _emitTopLevelName(element), genericInst]); |
1230 } | 1252 } |
1231 | 1253 |
1232 bool _deferIfNeeded(DartType type, ClassElement current) { | 1254 bool _deferIfNeeded(DartType type, ClassElement current) { |
1233 if (type is ParameterizedType) { | 1255 if (type is ParameterizedType) { |
1234 var typeArguments = type.typeArguments; | 1256 var typeArguments = type.typeArguments; |
1235 for (var typeArg in typeArguments) { | 1257 for (var typeArg in typeArguments) { |
1236 var typeElement = typeArg.element; | 1258 var typeElement = typeArg.element; |
1237 // FIXME(vsm): This does not track mutual recursive dependences. | 1259 // FIXME(vsm): This does not track mutual recursive dependencies. |
1238 if (current == typeElement || _deferIfNeeded(typeArg, current)) { | 1260 if (current == typeElement || _deferIfNeeded(typeArg, current)) { |
1239 return true; | 1261 return true; |
1240 } | 1262 } |
1241 } | 1263 } |
1242 } | 1264 } |
1243 return false; | 1265 return false; |
1244 } | 1266 } |
1245 | 1267 |
| 1268 JS.Expression _emitSyntheticSuperClassExpr( |
| 1269 ClassElement element, JS.Identifier id) { |
| 1270 var heritage = _emitClassHeritage(element, ignoreSynthetic: true); |
| 1271 var typeParams = _emitTypeFormals(element.typeParameters); |
| 1272 var methods = <JS.Method>[]; |
| 1273 |
| 1274 // Introduce the new forwarder with one-shot initialization support. |
| 1275 var body = <JS.Statement>[]; |
| 1276 |
| 1277 var virtualizeArguments = <JS.Expression>[]; |
| 1278 for (var field in _classProperties.virtualizedFields.keys) { |
| 1279 JS.TemporaryId fieldId = _classProperties.virtualizedFields[field]; |
| 1280 var name = _declareMemberName(field.getter); |
| 1281 virtualizeArguments.add(name); |
| 1282 virtualizeArguments.add(fieldId); |
| 1283 } |
| 1284 body.add(_callHelperStatement( |
| 1285 'virtualize(this, #);', new JS.ArrayInitializer(virtualizeArguments))); |
| 1286 body.add(js.statement('super.new.apply(this, arguments)')); |
| 1287 |
| 1288 var constructorName = _propertyName('new'); |
| 1289 methods.add(new JS.Method( |
| 1290 constructorName, js.call('function() { #; }', [body]) as JS.Fun)); |
| 1291 |
| 1292 for (var field in _classProperties.virtualizedFields.keys) { |
| 1293 JS.TemporaryId fieldId = _classProperties.virtualizedFields[field]; |
| 1294 var name = _declareMemberName(field.getter); |
| 1295 var getter = js.call('function() { return this[#]; }', [fieldId]); |
| 1296 methods.add(new JS.Method(name, getter, isGetter: true)); |
| 1297 var setter = js.call('function(value) { this[#] = value; }', [fieldId]); |
| 1298 methods.add(new JS.Method(name, setter, isSetter: true)); |
| 1299 } |
| 1300 |
| 1301 return new JS.ClassExpression(id, heritage, methods, |
| 1302 typeParams: typeParams); |
| 1303 } |
| 1304 |
1246 JS.ClassExpression _emitClassExpression( | 1305 JS.ClassExpression _emitClassExpression( |
1247 ClassElement element, List<JS.Method> methods, | 1306 ClassElement element, List<JS.Method> methods, |
1248 {List<FieldDeclaration> fields}) { | 1307 {List<FieldDeclaration> fields}) { |
1249 String name = element.name; | 1308 String name = element.name; |
1250 var heritage = _emitClassHeritage(element); | 1309 var heritage = _emitClassHeritage(element); |
1251 var typeParams = _emitTypeFormals(element.typeParameters); | 1310 var typeParams = _emitTypeFormals(element.typeParameters); |
1252 var jsFields = fields?.map(_emitTypeScriptField)?.toList(); | 1311 var jsFields = fields?.map(_emitTypeScriptField)?.toList(); |
1253 | 1312 |
1254 return new JS.ClassExpression(new JS.Identifier(name), heritage, methods, | 1313 return new JS.ClassExpression(new JS.Identifier(name), heritage, methods, |
1255 typeParams: typeParams, fields: jsFields); | 1314 typeParams: typeParams, fields: jsFields); |
1256 } | 1315 } |
1257 | 1316 |
1258 JS.Expression _emitClassHeritage(ClassElement element) { | 1317 JS.Expression _emitClassHeritage(ClassElement element, |
| 1318 {bool ignoreSynthetic = false}) { |
1259 var type = element.type; | 1319 var type = element.type; |
1260 if (type.isObject) return null; | 1320 if (type.isObject) return null; |
1261 | 1321 |
1262 _loader.startTopLevel(element); | 1322 _loader.startTopLevel(element); |
1263 | 1323 |
1264 // List of "direct" supertypes (supertype + mixins) | 1324 // List of "direct" supertypes (supertype + mixins) |
1265 var basetypes = [type.superclass]..addAll(type.mixins); | 1325 var basetypes = [type.superclass]..addAll(type.mixins); |
1266 | 1326 |
1267 // If any of these are recursive (via type parameter), defer setting | 1327 // If any of these are recursive (via type parameter), defer setting |
1268 // the real superclass. | 1328 // the real superclass. |
1269 if (basetypes.any((t) => _deferIfNeeded(t, element))) { | 1329 if (basetypes.any((t) => _deferIfNeeded(t, element))) { |
1270 // Fall back to raw type | 1330 // Fall back to raw type |
1271 basetypes = | 1331 basetypes = |
1272 basetypes.map((t) => fillDynamicTypeArgs(t.element.type)).toList(); | 1332 basetypes.map((t) => fillDynamicTypeArgs(t.element.type)).toList(); |
1273 _hasDeferredSupertype.add(element); | 1333 _hasDeferredSupertype.add(element); |
1274 } | 1334 } |
1275 | 1335 |
1276 // List of "direct" JS superclasses | 1336 // List of "direct" JS superclasses |
1277 var baseclasses = basetypes | 1337 var baseclasses = basetypes |
1278 .map((t) => _emitConstructorAccess(t, nameType: false)) | 1338 .map((t) => _emitConstructorAccess(t, nameType: false)) |
1279 .toList(); | 1339 .toList(); |
1280 assert(baseclasses.isNotEmpty); | 1340 assert(baseclasses.isNotEmpty); |
| 1341 |
| 1342 if (!ignoreSynthetic && |
| 1343 _classProperties != null && |
| 1344 _classProperties.virtualizedFields.isNotEmpty) { |
| 1345 // TODO(kasperl): we would want to have a unique generated ID here. |
| 1346 // We can't use 'TemporaryId' since a class is "declared" twice: |
| 1347 // var ClassName = class ClassName { ... } |
| 1348 var id = new JS.Identifier('${element.name}_${basetypes[0].name}'); |
| 1349 _syntheticSuperclasses[element] = id; |
| 1350 baseclasses = [id]; |
| 1351 } |
| 1352 |
1281 var heritage = (baseclasses.length == 1) | 1353 var heritage = (baseclasses.length == 1) |
1282 ? baseclasses.first | 1354 ? baseclasses.first |
1283 : _callHelper('mixin(#)', [baseclasses]); | 1355 : _callHelper('mixin(#)', [baseclasses]); |
1284 | 1356 |
1285 _loader.finishTopLevel(element); | 1357 _loader.finishTopLevel(element); |
1286 | 1358 |
1287 return heritage; | 1359 return heritage; |
1288 } | 1360 } |
1289 | 1361 |
1290 /// Provide Dart getters and setters that forward to the underlying native | 1362 /// Provide Dart getters and setters that forward to the underlying native |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1586 | 1658 |
1587 /// Emit a getter or setter that simply forwards to the superclass getter or | 1659 /// Emit a getter or setter that simply forwards to the superclass getter or |
1588 /// setter. This is needed because in ES6, if you only override a getter | 1660 /// setter. This is needed because in ES6, if you only override a getter |
1589 /// (alternatively, a setter), then there is an implicit override of the | 1661 /// (alternatively, a setter), then there is an implicit override of the |
1590 /// setter (alternatively, the getter) that does nothing. | 1662 /// setter (alternatively, the getter) that does nothing. |
1591 JS.Method _emitSuperAccessorWrapper( | 1663 JS.Method _emitSuperAccessorWrapper( |
1592 MethodDeclaration method, InterfaceType type) { | 1664 MethodDeclaration method, InterfaceType type) { |
1593 var methodElement = method.element as PropertyAccessorElement; | 1665 var methodElement = method.element as PropertyAccessorElement; |
1594 var field = methodElement.variable; | 1666 var field = methodElement.variable; |
1595 if (!field.isSynthetic) return null; | 1667 if (!field.isSynthetic) return null; |
| 1668 if (!(field.getter?.isAbstract == false || |
| 1669 field.setter?.isAbstract == false)) { |
| 1670 return null; |
| 1671 } |
1596 | 1672 |
1597 // Generate a corresponding virtual getter / setter. | 1673 // Generate a corresponding virtual getter / setter. |
1598 var name = _declareMemberName(methodElement); | 1674 var name = _declareMemberName(methodElement); |
1599 if (method.isGetter) { | 1675 if (method.isGetter) { |
1600 var setter = field.setter; | 1676 var setter = field.setter; |
1601 if ((setter == null || setter.isAbstract) && | 1677 if ((setter == null || setter.isAbstract) && |
1602 _classProperties.inheritedSetters.contains(field.name)) { | 1678 _classProperties.inheritedSetters.contains(field.name)) { |
1603 // Generate a setter that forwards to super. | 1679 // Generate a setter that forwards to super. |
1604 var fn = js.call('function(value) { super[#] = value; }', [name]); | 1680 var fn = js.call('function(value) { super[#] = value; }', [name]); |
1605 return new JS.Method(name, fn, isSetter: true); | 1681 return new JS.Method(name, fn, isSetter: true); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1679 ClassElement classElem, String jsPeerName, List<JS.Statement> body) { | 1755 ClassElement classElem, String jsPeerName, List<JS.Statement> body) { |
1680 if (jsPeerName != null) { | 1756 if (jsPeerName != null) { |
1681 body.add(_callHelperStatement('registerExtension(#.global.#, #);', [ | 1757 body.add(_callHelperStatement('registerExtension(#.global.#, #);', [ |
1682 _runtimeModule, | 1758 _runtimeModule, |
1683 _propertyName(jsPeerName), | 1759 _propertyName(jsPeerName), |
1684 _emitTopLevelName(classElem) | 1760 _emitTopLevelName(classElem) |
1685 ])); | 1761 ])); |
1686 } | 1762 } |
1687 } | 1763 } |
1688 | 1764 |
1689 JS.Statement _setBaseClass(ClassElement classElem, JS.Expression className, | 1765 /// Sets the baseclass of [classElem], represented by [targetClassName], to |
1690 List<String> jsPeerNames, List<JS.Statement> body) { | 1766 /// a "corrected" version of the base class. |
| 1767 /// |
| 1768 /// The [targetClassName] and [className] may differ if there is a |
| 1769 /// virtualization class injected in between the [classElem] and its |
| 1770 /// superclass. |
| 1771 JS.Statement _setBaseClass( |
| 1772 ClassElement classElem, |
| 1773 JS.Expression targetClassName, |
| 1774 JS.Expression className, |
| 1775 List<String> jsPeerNames, |
| 1776 List<JS.Statement> body) { |
1691 var typeFormals = classElem.typeParameters; | 1777 var typeFormals = classElem.typeParameters; |
1692 if (jsPeerNames.isNotEmpty && typeFormals.isNotEmpty) { | 1778 if (jsPeerNames.isNotEmpty && typeFormals.isNotEmpty) { |
1693 for (var peer in jsPeerNames) { | 1779 for (var peer in jsPeerNames) { |
1694 // TODO(jmesserly): we should just extend Array in the first place | 1780 // TODO(jmesserly): we should just extend Array in the first place |
1695 var newBaseClass = _callHelper('global.#', [peer]); | 1781 var newBaseClass = _callHelper('global.#', [peer]); |
1696 body.add(_callHelperStatement( | 1782 body.add(_callHelperStatement( |
1697 'setExtensionBaseClass(#, #);', [className, newBaseClass])); | 1783 'setExtensionBaseClass(#, #);', [targetClassName, newBaseClass])); |
1698 } | 1784 } |
1699 } else if (_hasDeferredSupertype.contains(classElem)) { | 1785 } else if (_hasDeferredSupertype.contains(classElem)) { |
1700 // TODO(vsm): consider just threading the deferred supertype through | 1786 // TODO(vsm): consider just threading the deferred supertype through |
1701 // instead of recording classElem in a set on the class and recomputing | 1787 // instead of recording classElem in a set on the class and recomputing |
1702 var newBaseClass = _emitType(classElem.type.superclass, | 1788 var newBaseClass = _emitType(classElem.type.superclass, |
1703 nameType: false, subClass: classElem, className: className); | 1789 nameType: false, subClass: classElem, className: className); |
1704 if (classElem.type.mixins.isNotEmpty) { | 1790 if (classElem.type.mixins.isNotEmpty) { |
1705 var mixins = classElem.type.mixins | 1791 var mixins = classElem.type.mixins |
1706 .map((t) => _emitType(t, nameType: false)) | 1792 .map((t) => _emitType(t, nameType: false)) |
1707 .toList(); | 1793 .toList(); |
1708 mixins.insert(0, newBaseClass); | 1794 mixins.insert(0, newBaseClass); |
1709 newBaseClass = _callHelper('mixin(#)', [mixins]); | 1795 newBaseClass = _callHelper('mixin(#)', [mixins]); |
1710 } | 1796 } |
1711 var deferredBaseClass = _callHelperStatement( | 1797 var deferredBaseClass = _callHelperStatement( |
1712 'setBaseClass(#, #);', [className, newBaseClass]); | 1798 'setBaseClass(#, #);', [targetClassName, newBaseClass]); |
1713 if (typeFormals.isNotEmpty) return deferredBaseClass; | 1799 if (typeFormals.isNotEmpty) return deferredBaseClass; |
1714 body.add(deferredBaseClass); | 1800 body.add(deferredBaseClass); |
1715 } | 1801 } |
1716 return null; | 1802 return null; |
1717 } | 1803 } |
1718 | 1804 |
1719 void _defineNamedConstructors(List<ConstructorDeclaration> ctors, | 1805 void _defineNamedConstructors(List<ConstructorDeclaration> ctors, |
1720 List<JS.Statement> body, JS.Expression className, bool isCallable) { | 1806 List<JS.Statement> body, JS.Expression className, bool isCallable) { |
1721 var code = isCallable | 1807 var code = isCallable |
1722 ? 'defineNamedConstructorCallable(#, #, #);' | 1808 ? 'defineNamedConstructorCallable(#, #, #);' |
(...skipping 3250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4973 js.call('(#[#._extensionType]) ? #[#[#]] : #.#', | 5059 js.call('(#[#._extensionType]) ? #[#[#]] : #.#', |
4974 [l, _runtimeModule, l, _extensionSymbolsModule, name, l, name]) | 5060 [l, _runtimeModule, l, _extensionSymbolsModule, name, l, name]) |
4975 ]); | 5061 ]); |
4976 } | 5062 } |
4977 return _callHelper('#(#, #)', | 5063 return _callHelper('#(#, #)', |
4978 [_emitDynamicOperationName('dload'), _visit(target), name]); | 5064 [_emitDynamicOperationName('dload'), _visit(target), name]); |
4979 } | 5065 } |
4980 | 5066 |
4981 var jsTarget = _emitTarget(target, member, isStatic); | 5067 var jsTarget = _emitTarget(target, member, isStatic); |
4982 bool isSuper = jsTarget is JS.Super; | 5068 bool isSuper = jsTarget is JS.Super; |
4983 if (isSuper && | |
4984 !member.isSynthetic && | |
4985 member is FieldElementImpl && | |
4986 !member.isVirtual) { | |
4987 // If super.x is a sealed field, then x is an instance property since | |
4988 // subclasses cannot override x. | |
4989 jsTarget = new JS.This(); | |
4990 } | |
4991 | |
4992 JS.Expression result; | 5069 JS.Expression result; |
4993 if (member != null && member is MethodElement && !isStatic) { | 5070 if (member != null && member is MethodElement && !isStatic) { |
4994 // Tear-off methods: explicitly bind it. | 5071 // Tear-off methods: explicitly bind it. |
4995 if (isSuper) { | 5072 if (isSuper) { |
4996 result = _callHelper('bind(this, #, #.#)', [name, jsTarget, name]); | 5073 result = _callHelper('bind(this, #, #.#)', [name, jsTarget, name]); |
4997 } else if (_isObjectMemberCall(target, memberName)) { | 5074 } else if (_isObjectMemberCall(target, memberName)) { |
4998 result = _callHelper('bind(#, #, #.#)', | 5075 result = _callHelper('bind(#, #, #.#)', |
4999 [jsTarget, _propertyName(memberName), _runtimeModule, memberName]); | 5076 [jsTarget, _propertyName(memberName), _runtimeModule, memberName]); |
5000 } else { | 5077 } else { |
5001 result = _callHelper('bind(#, #)', [jsTarget, name]); | 5078 result = _callHelper('bind(#, #)', [jsTarget, name]); |
(...skipping 888 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5890 if (targetIdentifier.staticElement is! PrefixElement) return false; | 5967 if (targetIdentifier.staticElement is! PrefixElement) return false; |
5891 var prefix = targetIdentifier.staticElement as PrefixElement; | 5968 var prefix = targetIdentifier.staticElement as PrefixElement; |
5892 | 5969 |
5893 // The library the prefix is referring to must come from a deferred import. | 5970 // The library the prefix is referring to must come from a deferred import. |
5894 var containingLibrary = resolutionMap | 5971 var containingLibrary = resolutionMap |
5895 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) | 5972 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) |
5896 .library; | 5973 .library; |
5897 var imports = containingLibrary.getImportsWithPrefix(prefix); | 5974 var imports = containingLibrary.getImportsWithPrefix(prefix); |
5898 return imports.length == 1 && imports[0].isDeferred; | 5975 return imports.length == 1 && imports[0].isDeferred; |
5899 } | 5976 } |
OLD | NEW |