| 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 |